/******************************************************************************/
/* @ All Rights Reserved Copyright (C) 2014 broada,Ltd.                       */
/*                                                                            */
/*  NAME      = db2_request.c                                                 */
/*  NOTE      = TDS 请求解析                                                  */
/*  DATE      = 2015/03/19 by zhengxd                                         */
/******************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>

#include "db2_core.h"
#include "db2_comm.h"
#include "db2_param.h"
#include "db2_obj.h"
#include "db2_request.h"

#define DRDA_SYNC_00    0x00 //None (CMNSYNCPT - Reuse connection)
#define DRDA_SYNC_01    0x01 //Prepare to commit
#define DRDA_SYNC_02    0x02 //Migrate resync responsibility to resync server
#define DRDA_SYNC_03    0x03 //Unit of work committed
#define DRDA_SYNC_04    0x04 //Unit of work rolled back
#define DRDA_SYNC_05    0x05 //Request to commit unit of work
#define DRDA_SYNC_06    0x06 //Forget unit of work
#define DRDA_SYNC_07    0x08 //Request log information
#define DRDA_SYNC_09    0x09 //New unit of work
#define DRDA_SYNC_0A    0x0A //Migrated resync responsibility
#define DRDA_SYNC_0B    0x0B //End association with unit of work
#define DRDA_SYNC_0C    0x0C //Return list of prepared and heuristically completed XIDs

/*******************************************************************************
*  FUNC     :  DDM request后处理
*  ARGS     :  p_st_conn (入力链接信息)
*           :  p_st_hash_report(保存Frreport_data)
*           :  p_st_private(DB2私有信息)
*           :  i_req_cmd_cp(request command类型)
*           :  i_sync_type(sync类型)
*  RTN      :  APM_L7_ANALYZE_SUCC  (success)
*              APM_L7_ANALYZE_TODO  (more data)
*              APM_L7_ANALYZE_FAIL  (failed)
*  NOTE     :
*******************************************************************************/
FR_STATIC int __db2_end_req_cmd(Conntrack *p_st_conn
                            , Frhash_header *p_st_hash_report
                            , L7session_db2_private *p_st_private
                            , int i_req_cmd_cp
                            , int i_sync_type)
{
    int i_ret = FR_SUCC;
    int i_new_flg = DB2_FALSE;
    unsigned long ul_req_sequence = 0;
    char *p_sql = NULL;
    int i_del_flg = DB2_FALSE;
    Db2_req_cmd *p_st_cmd = NULL;
    Frlist_header *p_lst_cmd = NULL;
    Frlist_node *p_st_node = NULL;
    Frlist_node *p_st_node_tmp = NULL;
    Frlist_node *p_hash_node = NULL;
    Sql_resultset *p_st_resultset = NULL;
    Sql_resultset *p_st_resultset_new = NULL;
    Sql_statement *p_st_statement = NULL;
    L7_req_db2 *p_st_req = p_st_private->p_st_req;
    Db2_req_cmd *p_st_cmd_pre = p_st_req->p_st_command_pre;
    L7_fragment_db2 *p_st_fragment = p_st_private->p_st_fragment;

    switch (i_req_cmd_cp)
    {
        /* PRPSQLSTT需要删除原来存在的hash值，并创建新的statement */
        case DRDA_CP_PRPSQLSTT:
            /* 根据session ID到hash表中找到是否有相同的 */
            p_hash_node = frhash2_getLong(p_st_private->p_hash_prepare
                                         , p_st_req->l_cursor_id);
            /* 取得statement数据 */
            p_st_statement = (Sql_statement *)FRLIST_GET_NODE_DATA(p_hash_node);
            if (p_st_statement)
            {
                /*
                *  一条request中可能有两个相同的cursor ID，
                * 此时还未上报不能直接删除，要保留待上报后删除
                */
                p_lst_cmd = &(p_st_req->st_command_lst);
                p_st_node = FRLIST_FIRST_NODE(p_lst_cmd);
                while (p_st_node)
                {
                    p_st_cmd = (Db2_req_cmd *)FRLIST_GET_NODE_DATA(p_st_node);
                    if (p_st_statement == p_st_cmd->p_st_statement)
                    {
                        /* 只删除节点，不删除节点内容 */
                        i_del_flg = DB2_TRUE;
                        frhash2_delLong(p_st_private->p_hash_prepare
                                       , p_st_req->l_cursor_id, NULL);
                        p_st_cmd->i_new_flg = DB2_TRUE;
                    }
                    p_st_node = FRLIST_NEXT_NODE(p_st_node);
                }
                /* 删除整个节点 */
                if (i_del_flg == DB2_FALSE)
                {
                    frhash2_delLong(p_st_private->p_hash_prepare
                                   , p_st_req->l_cursor_id
                                   , frdb_statement_node_free);
                }
            }

        /* EXCSQLIMM and EXCSQLSET is non-cursor Structured Query Language*/
        case DRDA_CP_EXCSQLIMM:
        case DRDA_CP_EXCSQLSET:
        case DRDA_CP_RDBCMM:
        case DRDA_CP_RDBRLLBCK:
        case DRDA_CP_SYNCCTL:
            /* 创建statement */
            p_st_statement = frdb_create_statement();
            if (p_st_statement == NULL)
            {
                frdbg("Create sqlbatch statement failed!\n");
                return APM_L7_ANALYZE_FAIL;
            }

            /* 设置sql语句 */
            if (i_req_cmd_cp == DRDA_CP_RDBRLLBCK)
            {
                p_sql = frstrdup("rollback");
                frdb_set_sql(p_st_statement, p_sql);
            }
            else if (i_req_cmd_cp == DRDA_CP_RDBCMM)
            {
                p_sql = frstrdup("commit");
                frdb_set_sql(p_st_statement, p_sql);
            }
            else if (i_req_cmd_cp == DRDA_CP_SYNCCTL)
            {
                switch (i_sync_type)
                {
                    case DRDA_SYNC_00: //None (CMNSYNCPT - Reuse connection)
                        p_sql = frstrdup("reuse connection");
                        break;

                    case DRDA_SYNC_01: //Prepare to commit
                        p_sql = frstrdup("prepare to commit");
                        break;

                    case DRDA_SYNC_02: //Migrate resync responsibility to resync server
                        p_sql = frstrdup("migrate resync");
                        break;

                    case DRDA_SYNC_03: //Unit of work committed
                        p_sql = frstrdup("transcation commit");
                        break;

                    case DRDA_SYNC_04: //Unit of work rolled back
                        p_sql = frstrdup("transcation rollback");
                        break;

                    case DRDA_SYNC_05: //Request to commit unit of work
                        p_sql = frstrdup("request to transcation commit");
                        break;

                    case DRDA_SYNC_06: //Forget unit of work
                        p_sql = frstrdup("forget transcation");
                        break;

                    case DRDA_SYNC_07: //Request log information
                        p_sql = frstrdup("request log information");
                        break;

                    case DRDA_SYNC_09: //New unit of work
                        p_sql = frstrdup("begin transcation");
                        break;

                    case DRDA_SYNC_0A: //Migrated resync responsibility
                        p_sql = frstrdup("migrated resync");
                        break;

                    case DRDA_SYNC_0B: //End association with unit of work
                        p_sql = frstrdup("end association with transcation");
                        break;

                    case DRDA_SYNC_0C: //Return list of prepared and heuristically completed XIDs
                        p_sql = frstrdup("return XIDs ");
                        break;

                    default:
                        p_sql = frstrdup("unknow transcation operate");
                        break;
                }
                frdb_set_sql(p_st_statement, p_sql);
            }
            else
            {
                frdb_set_sql(p_st_statement, p_st_req->p_sql);
                p_st_req->p_sql = NULL;
            }

            /* 创建结果集 */
            ul_req_sequence = frct_seq_increase(p_st_conn);
            p_st_resultset = frdb_create_resultset(ul_req_sequence);
            if (p_st_resultset == NULL)
            {
                frdbg("Create sqlbatch resultset failed!\n");
                frdb_statement_free(&p_st_statement);
                return APM_L7_ANALYZE_FAIL;
            }

            /* 追加结果集到statement */
            i_ret = frdb_add_resultset(p_st_statement, p_st_resultset);
            if (i_ret != FR_SUCC)
            {
                frdbg("Insert resultset into statement failed!\n");
                frdb_statement_free(&p_st_statement);
                frdb_resultset_free(&p_st_resultset);
                return APM_L7_ANALYZE_FAIL;
            }
            i_new_flg = DB2_TRUE;
            break;

        case DRDA_CP_OPNQRY:
        case DRDA_CP_CNTQRY:
        case DRDA_CP_CLSQRY:
        case DRDA_CP_DSCSQLSTT:
        case DRDA_CP_EXCSQLSTT:
            /* 当前COMMAND从属于上一个COMMAND */
            if (p_st_cmd_pre != NULL
                && p_st_cmd_pre->l_cursor_id == p_st_req->l_cursor_id)
            {
                p_st_statement = p_st_cmd_pre->p_st_statement;
                if (i_req_cmd_cp == DRDA_CP_OPNQRY
                    || i_req_cmd_cp == DRDA_CP_EXCSQLSTT)
                {
                    p_st_resultset = frdb_get_last_resultset(p_st_statement);
                }
                else
                {
                    p_st_resultset = p_st_cmd_pre->p_st_resultset;
                }
            }
            /* 需要到hash中找寻是否有相应的节点 */
            else
            {
                /* 根据session ID到hash表中找到是否有相同的 */
                p_hash_node = frhash2_getLong(p_st_private->p_hash_prepare
                                             , p_st_req->l_cursor_id);
                /* 取得statement数据 */
                p_st_statement = (Sql_statement *)FRLIST_GET_NODE_DATA(p_hash_node);
                /* 存在于hash中 */
                if (p_st_statement)
                {
                    /* 取得结果集resultset */
                    p_st_resultset = frdb_get_last_resultset(p_st_statement);
                    if (p_st_resultset == NULL)
                    {
                        frdbg("Get resultset failed!\n");
                        return APM_L7_ANALYZE_FAIL;
                    }
                    /*
                    * 如果是CLSQRY, 由于当前QUERY结束之后还有可能新的QUERY马上开始,
                    * 因此创建一个新的结果集用来存储新的QUERY结果集
                    */
                    if (i_req_cmd_cp == DRDA_CP_CLSQRY)
                    {
                        /* 创建结果集 */
                        ul_req_sequence = frct_seq_increase(p_st_conn);
                        p_st_resultset_new = frdb_create_resultset(ul_req_sequence);
                        if (p_st_resultset_new == NULL)
                        {
                            frdbg("Create sqlbatch resultset failed!\n");
                            return APM_L7_ANALYZE_FAIL;
                        }
                        /* 追加结果集到statement */
                        i_ret = frdb_add_resultset(p_st_statement, p_st_resultset_new);
                        if (i_ret != FR_SUCC)
                        {
                            frdbg("Insert resultset into statement failed!\n");
                            frdb_resultset_free(&p_st_resultset_new);
                            return APM_L7_ANALYZE_FAIL;
                        }
                    }
                }
                else
                {
                    /* 创建statement */
                    p_st_statement = frdb_create_statement();
                    if (p_st_statement == NULL)
                    {
                        frdbg("Create sqlbatch statement failed!\n");
                        return APM_L7_ANALYZE_FAIL;
                    }

                    /* 设置sql语句 */
                    frdb_set_sql(p_st_statement, p_st_req->p_sql);
                    p_st_req->p_sql = NULL;

                    /* 创建结果集 */
                    ul_req_sequence = frct_seq_increase(p_st_conn);
                    p_st_resultset = frdb_create_resultset(ul_req_sequence);
                    if (p_st_resultset == NULL)
                    {
                        frdbg("Create sqlbatch resultset failed!\n");
                        frdb_statement_free(&p_st_statement);
                        return APM_L7_ANALYZE_FAIL;
                    }

                    /* 追加结果集到statement */
                    i_ret = frdb_add_resultset(p_st_statement, p_st_resultset);
                    if (i_ret != FR_SUCC)
                    {
                        frdbg("Insert resultset into statement failed!\n");
                        frdb_statement_free(&p_st_statement);
                        frdb_resultset_free(&p_st_resultset);
                        return APM_L7_ANALYZE_FAIL;
                    }
                    i_new_flg = DB2_TRUE;
                }
            }
            break;

        default:
            break;
    }

    /* 释放request metadata */
    frlist_remove_all(&(p_st_req->st_metadata), frdb_metadata_node_free);
    if (p_st_resultset)
    {
        /* 将bind参数列表设置到result */
        p_st_node = FRLIST_FIRST_NODE(&(p_st_req->st_bind));
        while (p_st_node)
        {
            /* 追加节点 */
            p_st_node_tmp = p_st_node;
            p_st_node = FRLIST_NEXT_NODE(p_st_node);
            frlist_push(&(p_st_resultset->st_bind_list), p_st_node_tmp);
        }
        /* 清空request bind参数列 */
        memset(&(p_st_req->st_bind), 0x0, sizeof(Frlist_header));
    }

    /* 追加command节点 */
    i_ret = db2_add_req_cmd(p_st_private->p_st_req
                           , i_req_cmd_cp
                           , p_st_req->l_cursor_id
                           , i_new_flg
                           , p_st_statement
                           , p_st_resultset);
    if (i_ret != APM_L7_ANALYZE_SUCC)
    {
        if (i_new_flg == DB2_TRUE)
        {
            frdb_statement_free(&p_st_statement);
        }
        return APM_L7_ANALYZE_FAIL;
    }

    /* 更新请求结果集信息 */
    frdb_set_resultset_req2(p_st_resultset
                           , p_st_req->ui_ddm_len
                           , &(p_st_fragment->st_start_timestamp)
                           , &(p_st_fragment->st_timestamp));

    /* 初始化request, 为解析下一command做准备 */
    p_st_fragment->i_req_resp_cp = DRDA_CP_NULL;
    p_st_req->ui_ddm_len = 0;
    p_st_req->l_cursor_id = 0;
    if (p_st_req->p_sql)
    {
        printf("sql:[%s]\n", p_st_req->p_sql);
        frfree(p_st_req->p_sql);
    }
    p_st_req->p_sql = NULL;
    return APM_L7_ANALYZE_SUCC;
}

/*******************************************************************************
*  FUNC     :  解析EXCSAT
*  ARGS     :  p_st_conn (入力链接信息)
*           :  p_st_hash_report(保存Frreport_data)
*           :  p_st_req(request信息)
*  RTN      :  APM_L7_ANALYZE_SUCC  (success)
*              APM_L7_ANALYZE_FAIL  (failed)
*  NOTE     :
*******************************************************************************/
FR_STATIC int __db2_report_req(Conntrack *p_st_conn
                            , Frhash_header *p_st_hash_report
                            , L7_req_db2 *p_st_req
                            , L7session_db2 *p_st_sess)
{
    long l_report_pre = -1;
    int i_ret = APM_L7_ANALYZE_SUCC;
    Db2_req_cmd *p_st_cmd = NULL;
    Frlist_node *p_st_node = NULL;
    Frreport_body_data *p_st_report_body = NULL;

    /* 根据command list逐一上报 */
    p_st_node = FRLIST_FIRST_NODE(&(p_st_req->st_command_lst));
    while (p_st_node)
    {
        p_st_cmd = (Db2_req_cmd *)FRLIST_GET_NODE_DATA(p_st_node);
        switch (p_st_cmd->i_req_cmd_cp)
        {
            case DRDA_CP_CLSQRY:
            case DRDA_CP_EXCSQLSTT:
                /* 上一次已经上报过了 */
                if (l_report_pre == p_st_cmd->l_cursor_id)
                {
                    break;
                }
                l_report_pre = p_st_cmd->l_cursor_id;

            case DRDA_CP_EXCSQLSET:
            case DRDA_CP_RDBCMM:
            case DRDA_CP_EXCSQLIMM:
            case DRDA_CP_RDBRLLBCK:
            case DRDA_CP_SYNCCTL:
                /* 创建report body */
                p_st_report_body = db2_new_report_body(p_st_conn, p_st_sess);
                /* 创建report body失败时，不释放做成的request */
                if (p_st_report_body == NULL)
                {
                    frdbg("sqlserver_new_report_body failed!\n");
                    return APM_L7_ANALYZE_SUCC;
                }
                /* 上报request数据 */
                i_ret = frdb_report_req2(p_st_conn, p_st_hash_report
                                         , p_st_cmd->p_st_statement
                                         , p_st_cmd->p_st_resultset
                                         , &p_st_report_body);
                /* 上报request数据失败时，不释放做成的request */
                if (i_ret != FR_SUCC)
                {
                    frdbg("frdb_report_req2 failed!\n");
                    frreport_body_free(&p_st_report_body);
                    return APM_L7_ANALYZE_SUCC;
                }
                break;

            default:
                break;
        }

        /* 取得下一个节点 */
        p_st_node = FRLIST_NEXT_NODE(p_st_node);
    }

    return APM_L7_ANALYZE_SUCC;
}

/*******************************************************************************
*  FUNC     :  解析EXCSAT
*  ARGS     :  p_st_conn (入力链接信息)
*           :  p_st_hash_report(保存Frreport_data)
*           :  p_st_private(DB2私有数据)
*           :  i_whole_flg(packet是否完整)
*  RTN      :  APM_L7_ANALYZE_SUCC  (success)
*              APM_L7_ANALYZE_TODO  (more data)
*              APM_L7_ANALYZE_FAIL  (failed)
*  NOTE     :
*******************************************************************************/
FR_STATIC int __db2_parse_excsat(Conntrack *p_st_conn
                             , Frhash_header *p_st_hash_report
                             , L7session_db2_private *p_st_private
                             , int i_whole_flg)
{
    int i_ret = APM_L7_ANALYZE_SUCC;
    int i_param_cp = 0;
    unsigned int ui_param_bd_len = 0;
    L7session_db2 *p_st_sess = p_st_private->p_st_sess;
    L7_fragment_db2 *p_st_fragment = p_st_private->p_st_fragment;
    Frbyte_Packet *p_st_data = p_st_fragment->p_st_data;

    /*
    * 1.根据IBM官方协议说明, EXCSAT没有command data objects
    */
    if (p_st_fragment->i_correlator_flg == DB2_TRUE)
    {
        frdbg("EXCSAT: Format is incorrect!\n");
        return APM_L7_ANALYZE_FAIL;
    }

    /* 解析parameter */
    while (p_st_fragment->ui_left_ddm_len)
    {
        /* 取得EXCSAT的parameter */
        i_ret = db2_get_param_hd_info(p_st_fragment, i_whole_flg
                                     , &p_st_fragment->ui_left_ddm_len
                                     , &i_param_cp, &ui_param_bd_len);
        if (i_ret != APM_L7_ANALYZE_SUCC)
        {
            frdbg("EXCSAT: Need more data or parse failed!\n");
            return i_ret;
        }

        switch (i_param_cp)
        {
            /* EXTNAM/SPVNAM/SRVCLSNM/SRVRLSLV不取值,直接跳过 */
            case DRDA_CP_EXTNAM:    //External Name
            case DRDA_CP_SPVNAM:    //Supervisor Name
            case DRDA_CP_SRVCLSNM:  //Server Class Name
            case DRDA_CP_MGRLVLLS:  //Manager-level List(决定权在server)
                i_ret = db2_skip_param(p_st_data, ui_param_bd_len, i_whole_flg
                                      , &p_st_fragment->ui_left_ddm_len);
                break;

            /* 取得主机名 */
            case DRDA_CP_SRVNAM:
                /* 假如之前已经取到过,不再去取得(实际情况不大会发生) */
                if (p_st_sess->p_cli_host_user)
                {
                    i_ret = db2_skip_param(p_st_data, ui_param_bd_len, i_whole_flg
                                           , &p_st_fragment->ui_left_ddm_len);
                }
                else
                {
                    i_ret = db2_get_chrstrdr(p_st_data, ui_param_bd_len
                                            , i_whole_flg, p_st_sess->arr_ccsid
                                            , &p_st_sess->p_cli_host_user
                                            , &p_st_fragment->ui_left_ddm_len);
                }
                break;

            /* 取得客户端的程序名 */
            case DRDA_CP_SRVRLSLV:
                /* 假如之前已经取到过,不再去取得(实际情况不大会发生) */
                if (p_st_sess->p_program)
                {
                    i_ret = db2_skip_param(p_st_data, ui_param_bd_len, i_whole_flg
                                          , &p_st_fragment->ui_left_ddm_len);
                }
                else
                {
                    i_ret = db2_get_chrstrdr(p_st_data, ui_param_bd_len
                                            , i_whole_flg, p_st_sess->arr_ccsid
                                            , &p_st_sess->p_program
                                            , &p_st_fragment->ui_left_ddm_len);
                }
                break;

            default:
                frdbg("EXCSAT: Unkonw parameter code point!\n");
                return APM_L7_ANALYZE_FAIL;
        }

        /* 判断解析结果 */
        if (i_ret != APM_L7_ANALYZE_SUCC)
        {
            frdbg("EXCSAT: Need more data or skip parameter failed!\n");
            return i_ret;
        }
        /* 为取下一个参数做初始化准备 */
        p_st_fragment->i_param_cp = DRDA_CP_NULL;
    }

    /* 追加command point */
    i_ret = db2_add_req_cmd(p_st_private->p_st_req, DRDA_CP_EXCSAT
                           , DB2_FALSE, 0, NULL, NULL);
    if (i_ret != APM_L7_ANALYZE_SUCC)
    {
        frdbg("EXCSAT: Add request command failed!\n");
        return APM_L7_ANALYZE_FAIL;
    }

    /* 初始化code point, 为解析下一command做准备 */
    p_st_fragment->u64_parsed_index = bytebuff_getPosition(p_st_data);
    p_st_fragment->i_req_resp_cp = DRDA_CP_NULL;
    p_st_private->p_st_req->ui_ddm_len = 0;
    return APM_L7_ANALYZE_SUCC;
}

/*******************************************************************************
*  FUNC     :  解析ACCSEC
*  ARGS     :  p_st_conn (入力链接信息)
*           :  p_st_hash_report(保存Frreport_data)
*           :  p_st_private(DB2私有数据)
*           :  i_whole_flg(packet是否完整)
*  RTN      :  APM_L7_ANALYZE_SUCC  (success)
*              APM_L7_ANALYZE_TODO  (more data)
*              APM_L7_ANALYZE_FAIL  (failed)
*  NOTE     :
*******************************************************************************/
FR_STATIC int __db2_parse_accsec(Conntrack *p_st_conn
                             , Frhash_header *p_st_hash_report
                             , L7session_db2_private *p_st_private
                             , int i_whole_flg)
{
    int i_ret = APM_L7_ANALYZE_SUCC;
    int i_param_cp = 0;
    unsigned int ui_param_bd_len = 0;
    L7_req_db2 *p_st_req = p_st_private->p_st_req;
    L7session_db2 *p_st_sess = p_st_private->p_st_sess;
    L7_fragment_db2 *p_st_fragment = p_st_private->p_st_fragment;
    Frbyte_Packet *p_st_data = p_st_fragment->p_st_data;

    /*
    * 1.根据IBM官方协议说明, ACCSEC没有command data objects
    */
    if (p_st_fragment->i_correlator_flg == DB2_TRUE)
    {
        frdbg("ACCSEC: Format is incorrect!\n");
        return APM_L7_ANALYZE_FAIL;
    }

    /* 解析参数 */
    while (p_st_fragment->ui_left_ddm_len)
    {
        i_ret = db2_get_param_hd_info(p_st_fragment, i_whole_flg
                                     , &p_st_fragment->ui_left_ddm_len
                                     , &i_param_cp, &ui_param_bd_len);
        if (i_ret != APM_L7_ANALYZE_SUCC)
        {
            frdbg("ACCSEC: Need more data or parse failed!\n");
            return i_ret;
        }

        switch (i_param_cp)
        {
            /* SECMGRNM/SECMEC/SECTKN/ENCALG/ENCKEYLEN不取值,直接跳过 */
            case DRDA_CP_SECMGRNM:    //Security manager name
            case DRDA_CP_SECMEC:      //Security mechanism
            case DRDA_CP_SECTKN:      //Security token
            case DRDA_CP_ENCALG:      //Encryption algorithm
            case DRDA_CP_ENCKEYLEN:   //Encryption key length
            case DRDA_CP_PLGINID:     //Security Plug-in-specific Identifier
            case DRDA_CP_PLGINNM:     //Security Plug-in Name
                i_ret = db2_skip_param(p_st_data, ui_param_bd_len, i_whole_flg
                                      , &p_st_fragment->ui_left_ddm_len);
                break;

            /* 取得数据库名称 */
            case DRDA_CP_RDBNAM:
                /* 假如之前已经取到过,不再去取得(实际情况不大会发生) */
                if (p_st_sess->p_db_name)
                {
                    i_ret = db2_skip_param(p_st_data, ui_param_bd_len, i_whole_flg
                                          , &p_st_fragment->ui_left_ddm_len);
                }
                else
                {
                    i_ret = db2_get_chrstrdr(p_st_data, ui_param_bd_len
                                            , i_whole_flg, p_st_sess->arr_ccsid
                                            , &p_st_sess->p_db_name
                                            , &p_st_fragment->ui_left_ddm_len);
                }
                break;

            default:
                frdbg("ACCSEC: Unknow parameter code point!\n");
                return APM_L7_ANALYZE_FAIL;
        }

        /* 判断解析结果 */
        if (i_ret != APM_L7_ANALYZE_SUCC)
        {
            frdbg("ACCSEC: Need more data or skip parameter failed!\n");
            return i_ret;
        }
        /* 为取下一个参数做初始化准备 */
        p_st_fragment->i_param_cp = DRDA_CP_NULL;
    }

    /* 追加command point */
    i_ret = db2_add_req_cmd(p_st_req, DRDA_CP_ACCSEC, 0
                           , DB2_FALSE, NULL, NULL);
    if (i_ret != APM_L7_ANALYZE_SUCC)
    {
        frdbg("ACCSEC: add request command failed!\n");
        return APM_L7_ANALYZE_FAIL;
    }

    /* 初始化code point, 为解析下一command做准备 */
    p_st_fragment->u64_parsed_index = bytebuff_getPosition(p_st_data);
    p_st_fragment->i_req_resp_cp = DRDA_CP_NULL;
    p_st_req->ui_ddm_len = 0;
    return APM_L7_ANALYZE_SET_LOGIN(APM_L7_ANALYZE_SUCC);
}

/*******************************************************************************
*  FUNC     :  解析SECCHK
*  ARGS     :  p_st_conn (入力链接信息)
*           :  p_st_hash_report(保存Frreport_data)
*           :  p_st_private(DB2私有数据)
*           :  i_whole_flg(packet是否完整)
*  RTN      :  APM_L7_ANALYZE_SUCC  (success)
*              APM_L7_ANALYZE_TODO  (more data)
*              APM_L7_ANALYZE_FAIL  (failed)
*  NOTE     :
*******************************************************************************/
FR_STATIC int __db2_parse_secchk(Conntrack *p_st_conn
                             , Frhash_header *p_st_hash_report
                             , L7session_db2_private *p_st_private
                             , int i_whole_flg)
{
    int i_ret = APM_L7_ANALYZE_SUCC;
    int i_param_cp = 0;
    int i_obj_cp = 0;
    unsigned int ui_param_bd_len = 0;
    L7session_db2 *p_st_sess = p_st_private->p_st_sess;
    L7_fragment_db2 *p_st_fragment = p_st_private->p_st_fragment;
    Frbyte_Packet *p_st_data = p_st_fragment->p_st_data;

    /* 解析参数 */
    while (p_st_fragment->ui_left_ddm_len)
    {
        i_ret = db2_get_param_hd_info(p_st_fragment, i_whole_flg
                                     , &p_st_fragment->ui_left_ddm_len
                                     , &i_param_cp, &ui_param_bd_len);
        if (i_ret != APM_L7_ANALYZE_SUCC)
        {
            frdbg("SECCHK: need more data or parse failed!\n");
            return i_ret;
        }

        switch (i_param_cp)
        {
            /* 取得数据库名称 */
            case DRDA_CP_RDBNAM:
                /* 假如之前已经取到过,不再去取得 */
                if (p_st_sess->p_db_name)
                {
                    i_ret = db2_skip_param(p_st_data, ui_param_bd_len, i_whole_flg
                                          , &p_st_fragment->ui_left_ddm_len);
                }
                else
                {
                    i_ret = db2_get_chrstrdr(p_st_data, ui_param_bd_len
                                            , i_whole_flg, p_st_sess->arr_ccsid
                                            , &p_st_sess->p_db_name
                                            , &p_st_fragment->ui_left_ddm_len);
                }
                break;

            /* 取得登陆用户名 */
            case DRDA_CP_USRID:
                /* 假如之前已经取到过,不再去取得 */
                if (p_st_sess->p_db_user)
                {
                    i_ret = db2_skip_param(p_st_data, ui_param_bd_len, i_whole_flg
                                          , &p_st_fragment->ui_left_ddm_len);
                }
                else
                {
                    i_ret = db2_get_chrstrdr(p_st_data, ui_param_bd_len
                                            , i_whole_flg, p_st_sess->arr_ccsid
                                            , &p_st_sess->p_db_user
                                            , &p_st_fragment->ui_left_ddm_len);
                }
                break;

            /* 不取值,直接跳过 */
            case DRDA_CP_NEWPASSWORD:  //New Password
            case DRDA_CP_PLGINID:      //Security Plug-in-specific Identifier
            case DRDA_CP_PLGINNM:      //Security Plug-in Name
            case DRDA_CP_PASSWORD:     //Password
            case DRDA_CP_SECMEC:       //Security Mechanism
            case DRDA_CP_SECMGRNM:     //Security Manager Name
            case DRDA_CP_SECTKN:       //Security Token
            case DRDA_CP_USRORGID:     //user original user id
            case DRDA_CP_USRREGNM:     //security registry name
            case DRDA_CP_USRSECTOK:    //user security token
                i_ret = db2_skip_param(p_st_data, ui_param_bd_len, i_whole_flg
                                      , &p_st_fragment->ui_left_ddm_len);
                break;

            default:
                frdbg("SECCHK: Unkonw parameter!\n");
                return APM_L7_ANALYZE_FAIL;
        }

        /* 判断解析结果 */
        if (i_ret != APM_L7_ANALYZE_SUCC)
        {
            frdbg("SECCHK: need more data or skip parameter failed!\n");
            return i_ret;
        }
        /* 为取下一个参数做初始化准备 */
        p_st_fragment->i_param_cp = DRDA_CP_NULL;
    }
    /* 设置position */
    p_st_fragment->u64_parsed_index = bytebuff_getPosition(p_st_data);

    /* 解析SECCHK的command object */
    while (bytebuff_remaining(p_st_data) > 0)
    {
        /* 取得当前command object的code point */
        i_ret = db2_get_obj_cp(p_st_fragment, i_whole_flg, &i_obj_cp
                              , &p_st_private->p_st_req->ui_ddm_len);
        if (i_ret != APM_L7_ANALYZE_SUCC)
        {
            frdbg("SECTKN: need more data or parse failed!\n");
            return i_ret;
        }

        switch(i_obj_cp)
        {
            /* SECTKN command object解析完了 */
            case DRDA_CP_NULL:
                /* SECTKN的后处理 */
                i_ret = db2_add_req_cmd(p_st_private->p_st_req, DRDA_CP_SECCHK
                                        , DB2_FALSE, 0, NULL, NULL);
                if (i_ret != APM_L7_ANALYZE_SUCC)
                {
                    frdbg("SECCHK: add request command failed!\n");
                    return APM_L7_ANALYZE_FAIL;
                }
                p_st_fragment->i_req_resp_cp = DRDA_CP_NULL;
                p_st_private->p_st_req->ui_ddm_len = 0;
                return APM_L7_ANALYZE_SUCC;

            /* 跳过该command object */
            case DRDA_CP_SECTKN:
                i_ret = db2_skip_cmd_obj(p_st_fragment, i_whole_flg);
                if (i_ret != APM_L7_ANALYZE_SUCC)
                {
                    frdbg("SECTKN: need more data or parse failed!\n");
                    return i_ret;
                }
                break;

            default:
                frdbg("SECCHK: command object is incorrect!\n");
                return APM_L7_ANALYZE_FAIL;
        }

        /* 设置position */
        p_st_fragment->u64_parsed_index = bytebuff_getPosition(p_st_data);
        /* 初始化object command信息 */
        i_obj_cp = DRDA_CP_NULL;
        p_st_fragment->i_obj_cp = DRDA_CP_NULL;
        p_st_fragment->ui_left_obj_len = 0;
    }

    /* 整个request解析完了 */
    if (p_st_fragment->i_correlator_flg == DB2_FALSE || i_whole_flg == DB2_TRUE)
    {
        p_st_fragment->u64_parsed_index = bytebuff_getPosition(p_st_data);
        p_st_fragment->i_req_resp_cp = DRDA_CP_NULL;
        p_st_private->p_st_req->ui_ddm_len = 0;
        /* 追加command point */
        i_ret = db2_add_req_cmd(p_st_private->p_st_req, DRDA_CP_SECCHK
                               , DB2_FALSE, 0, NULL, NULL);
        if (i_ret != APM_L7_ANALYZE_SUCC)
        {
            frdbg("SECCHK: add request command failed!\n");
            return APM_L7_ANALYZE_FAIL;
        }
        return APM_L7_ANALYZE_SUCC;
    }
    else
    {
        return APM_L7_ANALYZE_TODO;
    }
}

/*******************************************************************************
*  FUNC     :  解析ACCRDB
*  ARGS     :  p_st_conn (入力链接信息)
*           :  p_st_hash_report(保存Frreport_data)
*           :  p_st_private(DB2私有数据)
*           :  i_whole_flg(packet是否完整)
*  RTN      :  APM_L7_ANALYZE_SUCC  (success)
*              APM_L7_ANALYZE_TODO  (more data)
*              APM_L7_ANALYZE_FAIL  (failed)
*  NOTE     :
*******************************************************************************/
FR_STATIC int __db2_parse_accrdb(Conntrack *p_st_conn
                             , Frhash_header *p_st_hash_report
                             , L7session_db2_private *p_st_private
                             , int i_whole_flg)
{
    int i_ret = APM_L7_ANALYZE_SUCC;
    int i_param_cp = 0;
    unsigned int ui_param_bd_len = 0;
    char *p_typdefnam = NULL;
    L7session_db2 *p_st_sess = p_st_private->p_st_sess;
    L7_fragment_db2 *p_st_fragment = p_st_private->p_st_fragment;
    Frbyte_Packet *p_st_data = p_st_fragment->p_st_data;

    /*
    * 1.根据IBM官方协议说明, ACCRDB没有command data objects
    */
    if (p_st_fragment->i_correlator_flg == DB2_TRUE)
    {
        frdbg("ACCRDB format is incorrect!\n");
        return APM_L7_ANALYZE_FAIL;
    }

    /* 解析参数 */
    while (p_st_fragment->ui_left_ddm_len)
    {
        i_ret = db2_get_param_hd_info(p_st_fragment, i_whole_flg
                                     , &p_st_fragment->ui_left_ddm_len
                                     , &i_param_cp, &ui_param_bd_len);
        if (i_ret != APM_L7_ANALYZE_SUCC)
        {
            frdbg("ACCRDB: need more data or parse failed!\n");
            return i_ret;
        }

        switch (i_param_cp)
        {
            /* SECMGRNM/SECMEC/SECTKN/ENCALG/ENCKEYLEN不取值,直接跳过 */
            case DRDA_CP_ARMCORR:    //ARM correlator
            case DRDA_CP_CRRTKN:     //correlation token
            case DRDA_CP_DIAGLVL:    //diagnostic level
            //case DRDA_CP_DIAGNOSTICS: //SQL error diagnostic level(与DIAGLVL重复)
            case DRDA_CP_PRDDTA:     //product-specific data
            case DRDA_CP_RDBACCCL:   //RDB access manager class
            case DRDA_CP_RDBALWUPD:  //RDB allows updates
            case DRDA_CP_SLA:        //Service-Level Agreement
            case DRDA_CP_STTDECDEL:  //statement decimal delimiter
            case DRDA_CP_STTSTRDEL:  //statement string delimiter
            case DRDA_CP_TRGDFTRT:   //target default values return
            case DRDA_CP_TRUST:      //access as a trusted entity
            case DRDA_CP_TYPDEFOVR:  //access as a trusted entity(TODO)
            case DRDA_CP_UNPUPDALW:  //access as a trusted entity
                i_ret = db2_skip_param(p_st_data, ui_param_bd_len, i_whole_flg
                                      , &p_st_fragment->ui_left_ddm_len);
                break;

            /* 取得客户端TYPDEFNAM */
            case DRDA_CP_TYPDEFNAM:
                i_ret = db2_get_chrstrdr(p_st_data, ui_param_bd_len
                                        , i_whole_flg, p_st_sess->arr_ccsid
                                        , &p_typdefnam
                                        , &p_st_fragment->ui_left_ddm_len);
                /* 判断解析结果 */
                if (i_ret != APM_L7_ANALYZE_SUCC)
                {
                    frdbg("ACCRDB: need more data or parse failed!\n");
                    return i_ret;
                }

                i_ret = db2_typdef_str2int(p_typdefnam, &p_st_sess->i_cli_typdef);
                db2_free((void **)&p_typdefnam);
                if (i_ret != APM_L7_ANALYZE_SUCC)
                {
                    frdbg("ACCRDB: TYPDEFNAM is undefined!\n");
                    return APM_L7_ANALYZE_FAIL;
                }
                break;

            /* 取得客户端程序名称 */
            case DRDA_CP_PRDID:
                /* 假如之前已经取到过,不再去取得(实际情况不大会发生) */
                if (p_st_sess->p_program)
                {
                    i_ret = db2_skip_param(p_st_data, ui_param_bd_len, i_whole_flg
                                          , &p_st_fragment->ui_left_ddm_len);
                }
                else
                {
                    i_ret = db2_get_chrstrdr(p_st_data, ui_param_bd_len
                                            , i_whole_flg, p_st_sess->arr_ccsid
                                            , &p_st_sess->p_program
                                            , &p_st_fragment->ui_left_ddm_len);
                }
                break;

            /* 取得数据库名称 */
            case DRDA_CP_RDBNAM:
                /* 假如之前已经取到过,不再去取得 */
                if (p_st_sess->p_db_name)
                {
                    i_ret = db2_skip_param(p_st_data, ui_param_bd_len, i_whole_flg
                                          , &p_st_fragment->ui_left_ddm_len);
                }
                else
                {
                    i_ret = db2_get_chrstrdr(p_st_data, ui_param_bd_len
                                            , i_whole_flg, p_st_sess->arr_ccsid
                                            , &p_st_sess->p_db_name
                                            , &p_st_fragment->ui_left_ddm_len);
                }
                break;

            default:
                frdbg("ACCRDB: Unknow parameter code point!\n");
                return APM_L7_ANALYZE_FAIL;
        }

        /* 判断解析结果 */
        if (i_ret != APM_L7_ANALYZE_SUCC)
        {
            frdbg("ACCRDB: need more data or parse failed!\n");
            return i_ret;
        }
        /* 为取下一个参数做初始化准备 */
        p_st_fragment->i_param_cp = DRDA_CP_NULL;
    }

    /* 追加command point */
    i_ret = db2_add_req_cmd(p_st_private->p_st_req, DRDA_CP_ACCRDB
                           , DB2_FALSE, 0, NULL, NULL);
    if (i_ret != APM_L7_ANALYZE_SUCC)
    {
        frdbg("ACCRDB: add request command failed!\n");
        return APM_L7_ANALYZE_FAIL;
    }

    /* 设置position */
    p_st_fragment->u64_parsed_index = bytebuff_getPosition(p_st_data);
    /* 初始化code point, 为解析下一command做准备 */
    p_st_fragment->i_req_resp_cp = DRDA_CP_NULL;
    p_st_private->p_st_req->ui_ddm_len = 0;
    return APM_L7_ANALYZE_SUCC;
}

/*******************************************************************************
*  FUNC     :  解析EXCSQLSET
*  ARGS     :  p_st_conn (入力链接信息)
*           :  p_st_hash_report(保存Frreport_data)
*           :  p_st_private(DB2私有数据)
*           :  i_whole_flg(packet是否完整)
*  RTN      :  APM_L7_ANALYZE_SUCC  (success)
*              APM_L7_ANALYZE_TODO  (more data)
*              APM_L7_ANALYZE_FAIL  (failed)
*  NOTE     :
*******************************************************************************/
FR_STATIC int __db2_parse_excsqlset(Conntrack *p_st_conn
                                , Frhash_header *p_st_hash_report
                                , L7session_db2_private *p_st_private
                                , int i_whole_flg)
{
    int i_ret = APM_L7_ANALYZE_SUCC;
    int i_obj_cp = 0;
    int i_param_cp = 0;
    int64_t i64_sess_num = 0;
    unsigned int ui_param_bd_len = 0;
    L7_req_db2 *p_st_req = p_st_private->p_st_req;
    L7_fragment_db2 *p_st_fragment = p_st_private->p_st_fragment;
    Frbyte_Packet *p_st_data = p_st_fragment->p_st_data;

    /* 解析EXCSQLSET参数 */
    while (p_st_fragment->ui_left_ddm_len)
    {
        i_ret = db2_get_param_hd_info(p_st_fragment, i_whole_flg
                                     , &p_st_fragment->ui_left_ddm_len
                                     , &i_param_cp, &ui_param_bd_len);
        if (i_ret != APM_L7_ANALYZE_SUCC)
        {
            frdbg("EXCSQLSET: need more data or parse failed!\n");
            return i_ret;
        }

        switch (i_param_cp)
        {
            /* 直接跳过如下参数 */
            case DRDA_CP_MONITOR:   //monitor events
            case DRDA_CP_RDBNAM:    //RDB name, as in ACCRDB
            case DRDA_CP_RTNSETSTT: //Return SQL Statement
            case DRDA_CP_PKGNAMCT:  //RDB Package Name and Consistency token
            //case DRDA_CP_PKGSN:     //RDB Package Section Number
            //case DRDA_CP_PKGNAMCSN: //package name, consistency token and section number
                i_ret = db2_skip_param(p_st_data, ui_param_bd_len, i_whole_flg
                                      , &p_st_fragment->ui_left_ddm_len);
                break;

            case DRDA_CP_PKGSN:     //RDB Package Section Number
                /* 根据协议长度是16bits, 即是2byte */
                if (ui_param_bd_len != 2)
                {
                    frdbg("EXCSQLSTT: PKGSN parameter length is incorrect!\n");
                    return APM_L7_ANALYZE_FAIL;
                }
                /* 此处的length是bits, 16bit就是2byte */
                i_ret = db2_get_bindr(p_st_data, 2, i_whole_flg, &i64_sess_num
                                     , &p_st_fragment->ui_left_ddm_len);
                /* 设置session number */
                p_st_req->l_cursor_id = (long)i64_sess_num;
                break;

            /* 取得section number */
            case DRDA_CP_PKGNAMCSN: //package name, consistency token and section number
                i_ret = db2_get_sess_num(p_st_data, ui_param_bd_len, i_whole_flg
                                        , &p_st_fragment->ui_left_ddm_len
                                        , &i64_sess_num);
                /* 设置session number */
                p_st_req->l_cursor_id = (long)i64_sess_num;
                break;

            default:
                frdbg("EXCSQLSET: Unkonw parameter!\n");
                return APM_L7_ANALYZE_FAIL;
        }

        /* 判断解析结果 */
        if (i_ret != APM_L7_ANALYZE_SUCC)
        {
            frdbg("EXCSQLSET: need more data or skip parameter failed!\n");
            return i_ret;
        }
        /* 为取下一个参数做初始化准备 */
        p_st_fragment->i_param_cp = DRDA_CP_NULL;
    }

    /* 设置position */
    p_st_fragment->u64_parsed_index = bytebuff_getPosition(p_st_data);

    /* 解析EXCSQLSET的command object */
    while (bytebuff_remaining(p_st_data) > 0)
    {
        /* 取得当前command object的code point */
        i_ret = db2_get_obj_cp(p_st_fragment, i_whole_flg
                              , &i_obj_cp, &p_st_req->ui_ddm_len);
        if (i_ret != APM_L7_ANALYZE_SUCC)
        {
            frdbg("EXCSQLSET: need more data or parse failed!\n");
            return i_ret;
        }

        /* 跳过该command object */
        switch(i_obj_cp)
        {
            /* EXCSQLSET的command object解析完了 */
            case DRDA_CP_NULL:
                /* EXCSQLSET后处理 */
                i_ret = __db2_end_req_cmd(p_st_conn, p_st_hash_report
                                         , p_st_private, DRDA_CP_EXCSQLSET, -1);
                if (i_ret != APM_L7_ANALYZE_SUCC)
                {
                    frdbg("EXCSQLSET: Add command list faield!\n");
                }
                return i_ret;

            /* 跳过一下command object */
            case DRDA_CP_SECTKNOVR:
            case DRDA_CP_TYPDEFNAM:
            case DRDA_CP_TYPDEFOVR:
                i_ret = db2_skip_cmd_obj(p_st_fragment, i_whole_flg);
                break;

            /* 解析sql语句 */
            case DRDA_CP_SQLSTT:   //SQL statement
                i_ret = db2_get_sqlstt(p_st_fragment, i_whole_flg
                                      , &p_st_req->p_sql);

                break;

            default:
                frdbg("EXCSQLSET: Unknow command object!\n");
                return APM_L7_ANALYZE_FAIL;
        }

        /* 解析结果判定 */
        if (i_ret != APM_L7_ANALYZE_SUCC)
        {
            frdbg("EXCSQLSET: need more data or parse failed!\n");
            return i_ret;
        }
        /* 设置position */
        p_st_fragment->u64_parsed_index = bytebuff_getPosition(p_st_data);
        /* 初始化object command信息 */
        i_obj_cp = DRDA_CP_NULL;
        p_st_fragment->i_obj_cp = DRDA_CP_NULL;
        p_st_fragment->ui_left_obj_len = 0;
    }

    /* 整个request接收完了 */
    if (p_st_fragment->i_correlator_flg == DB2_FALSE || i_whole_flg == DB2_TRUE)
    {
        /* EXCSQLSET后处理 */
        i_ret = __db2_end_req_cmd(p_st_conn, p_st_hash_report
                                 , p_st_private, DRDA_CP_EXCSQLSET, -1);
        if (i_ret != APM_L7_ANALYZE_SUCC)
        {
            frdbg("EXCSQLSET: add command list faield!\n");
        }
        return i_ret;
    }
    else
    {
        return APM_L7_ANALYZE_TODO;
    }
}

/*******************************************************************************
*  FUNC     :  解析PRPSQLSTT
*  ARGS     :  p_st_conn (入力链接信息)
*           :  p_st_hash_report(保存Frreport_data)
*           :  p_st_private(DB2私有数据)
*           :  i_whole_flg(packet是否完整)
*  RTN      :  APM_L7_ANALYZE_SUCC  (success)
*              APM_L7_ANALYZE_TODO  (more data)
*              APM_L7_ANALYZE_FAIL  (failed)
*  NOTE     :
*******************************************************************************/
FR_STATIC int __db2_parse_prpsqlstt(Conntrack *p_st_conn
                                , Frhash_header *p_st_hash_report
                                , L7session_db2_private *p_st_private
                                , int i_whole_flg)
{
    int i_ret = APM_L7_ANALYZE_SUCC;
    int i_obj_cp = 0;
    int i_param_cp = 0;
    int64_t i64_sess_num = 0;
    unsigned int ui_param_bd_len = 0;
    L7_req_db2 *p_st_req = p_st_private->p_st_req;
    L7_fragment_db2 *p_st_fragment = p_st_private->p_st_fragment;
    Frbyte_Packet *p_st_data = p_st_fragment->p_st_data;

    /* 解析参数 */
    while (p_st_fragment->ui_left_ddm_len)
    {
        i_ret = db2_get_param_hd_info(p_st_fragment, i_whole_flg
                                     , &p_st_fragment->ui_left_ddm_len
                                     , &i_param_cp, &ui_param_bd_len);
        if (i_ret != APM_L7_ANALYZE_SUCC)
        {
            frdbg("PRPSQLSTT: need more data or parse failed!\n");
            return i_ret;
        }

        switch (i_param_cp)
        {
            /* 直接跳过如下参数 */
            case DRDA_CP_BUFINSIND: //Buffered Insert Indicator
            case DRDA_CP_CMDSRCID:  //command source identifier
            case DRDA_CP_MONITOR:   //monitor events
            case DRDA_CP_RDBNAM:    //RDB name, as in ACCRDB
            case DRDA_CP_RTNSQLDA:  //return SQL descriptor area
            case DRDA_CP_TYPSQLDA:  //type of descriptor to return
                i_ret = db2_skip_param(p_st_data, ui_param_bd_len, i_whole_flg
                                      , &p_st_fragment->ui_left_ddm_len);
                break;

            /* 取得section number */
            case DRDA_CP_PKGSN:     //RDB package section number
                /* 根据协议长度是16bits, 即是2byte */
                if (ui_param_bd_len != 2)
                {
                    frdbg("EXCSQLSTT: PKGSN parameter length is incorrect!\n");
                    return APM_L7_ANALYZE_FAIL;
                }
                /* 此处的length是bits, 16bit就是2byte */
                i_ret = db2_get_bindr(p_st_data, 2, i_whole_flg, &i64_sess_num
                                     , &p_st_fragment->ui_left_ddm_len);
                /* 设置session number */
                p_st_req->l_cursor_id = (long)i64_sess_num;
                break;

            case DRDA_CP_PKGNAMCSN: //package name, consistency token and section number
                i_ret = db2_get_sess_num(p_st_data, ui_param_bd_len, i_whole_flg
                                        , &p_st_fragment->ui_left_ddm_len
                                        , &i64_sess_num);
                /* 设置session number */
                p_st_req->l_cursor_id = (long)i64_sess_num;
                break;

            default:
                frdbg("PRPSQLSTT: Unkonw parameter!\n");
                return APM_L7_ANALYZE_FAIL;
        }

        /* 判断解析结果 */
        if (i_ret != APM_L7_ANALYZE_SUCC)
        {
            frdbg("PRPSQLSTT: need more data or parse failed!\n");
            return i_ret;
        }
        /* 为取下一个参数做初始化准备 */
        p_st_fragment->i_param_cp = DRDA_CP_NULL;
    }

    /* 设置position */
    p_st_fragment->u64_parsed_index = bytebuff_getPosition(p_st_data);
    /* 解析PRPSQLSTT的command object */
    while (bytebuff_remaining(p_st_data) > 0)
    {
        /* 取得当前command object的code point */
        i_ret = db2_get_obj_cp(p_st_fragment, i_whole_flg, &i_obj_cp
                              , &p_st_private->p_st_req->ui_ddm_len);
        if (i_ret != APM_L7_ANALYZE_SUCC)
        {
            frdbg("PRPSQLSTT: need more data or parse failed!\n");
            return i_ret;
        }

        /* 跳过该command object */
        switch(i_obj_cp)
        {
            /* PRPSQLSTT的command object解析完了 */
            case DRDA_CP_NULL:
                /* PRPSQLSTT的后处理 */
                i_ret = __db2_end_req_cmd(p_st_conn, p_st_hash_report
                                          , p_st_private, DRDA_CP_PRPSQLSTT, -1);
                if (i_ret != APM_L7_ANALYZE_SUCC)
                {
                    frdbg("PRPSQLSTT: add command list failed!\n");
                }
                return i_ret;

            /* 跳过正常的SECTKNOVR/TYPDEFOVR/SQLATTR/TYPDEFNAM */
            case DRDA_CP_SECTKNOVR: //sectkn overrides
            case DRDA_CP_TYPDEFOVR: //data type definition override
            case DRDA_CP_SQLATTR:   //SQL statement attributes
            case DRDA_CP_TYPDEFNAM: //data type definition name
                i_ret = db2_skip_cmd_obj(p_st_fragment, i_whole_flg);
                break;

            /* 解析sql语句 */
            case DRDA_CP_SQLSTT:   //SQL statement
                i_ret = db2_get_sqlstt(p_st_fragment, i_whole_flg
                                      , &p_st_req->p_sql);
                break;

            default:
                frdbg("PRPSQLSTT: Unknow command object!\n");
                return APM_L7_ANALYZE_FAIL;
        }

        /* 解析结果判定 */
        if (i_ret != APM_L7_ANALYZE_SUCC)
        {
            frdbg("PRPSQLSTT: need more data or parse failed!\n");
            return i_ret;
        }

        /* 设置position */
        p_st_fragment->u64_parsed_index = bytebuff_getPosition(p_st_data);
        /* 初始化object command信息 */
        i_obj_cp = DRDA_CP_NULL;
        p_st_fragment->i_obj_cp = DRDA_CP_NULL;
        p_st_fragment->ui_left_obj_len = 0;
    }

    /* 整个request解析完了 */
    if (p_st_fragment->i_correlator_flg == DB2_FALSE || i_whole_flg == DB2_TRUE)
    {
        /* PRPSQLSTT后处理 */
        i_ret = __db2_end_req_cmd(p_st_conn, p_st_hash_report
                                 , p_st_private, DRDA_CP_PRPSQLSTT, -1);
        if (i_ret != APM_L7_ANALYZE_SUCC)
        {
            frdbg("PRPSQLSTT: add command list failed!\n");
        }
        return i_ret;
    }
    else
    {
        return APM_L7_ANALYZE_TODO;
    }
}

/*******************************************************************************
*  FUNC     :  解析OPNQRY
*  ARGS     :  p_st_conn (入力链接信息)
*           :  p_st_hash_report(保存Frreport_data)
*           :  p_st_private(DB2私有数据)
*           :  i_whole_flg(packet是否完整)
*  RTN      :  APM_L7_ANALYZE_SUCC  (success)
*              APM_L7_ANALYZE_TODO  (more data)
*              APM_L7_ANALYZE_FAIL  (failed)
*  NOTE     :
*******************************************************************************/
FR_STATIC int __db2_parse_opnqry(Conntrack *p_st_conn
                             , Frhash_header *p_st_hash_report
                             , L7session_db2_private *p_st_private
                             , int i_whole_flg)
{
    int i_ret = APM_L7_ANALYZE_SUCC;
    int i_obj_cp = 0;
    int i_param_cp = 0;
    int64_t i64_sess_num = 0;
    unsigned int ui_param_bd_len = 0;
    char *p_typdefnam = NULL;
    L7_req_db2 *p_st_req = p_st_private->p_st_req;
    L7_fragment_db2 *p_st_fragment = p_st_private->p_st_fragment;
    Frbyte_Packet *p_st_data = p_st_fragment->p_st_data;

    /* 解析OPNQRY command */
    while (p_st_fragment->ui_left_ddm_len)
    {
        i_ret = db2_get_param_hd_info(p_st_fragment, i_whole_flg
                                     , &p_st_fragment->ui_left_ddm_len
                                     , &i_param_cp, &ui_param_bd_len);
        if (i_ret != APM_L7_ANALYZE_SUCC)
        {
            frdbg("OPNQRY: need more data or parse failed!\n");
            return i_ret;
        }

        switch (i_param_cp)
        {
            /* 直接跳过如下参数 */
            case DRDA_CP_CMDSRCID:    //command source identifier
            case DRDA_CP_DFTFMTXML:   //Default Format for XML Data
            case DRDA_CP_DUPQRYOK:    //command source identifier)
            case DRDA_CP_DYNDTAFMT:   //dynamic data format
            case DRDA_CP_MAXBLKEXT:   //maximum number of additional query blocks
            case DRDA_CP_MEDDTASZ:    //maximum size of medium data
            case DRDA_CP_MONITOR:     //monitor events
            case DRDA_CP_OUTOVROPT:   //output option
            case DRDA_CP_OUTOVRXML:   //Output Option for XML Data
            case DRDA_CP_QRYBLKCTL:   //query block protocol control
            case DRDA_CP_QRYBLKSZ:    //query block size
            case DRDA_CP_QRYCLSIMP:   //query close implicit
            case DRDA_CP_QRYCLSRLS:   //query close lock release
            case DRDA_CP_QRYEXTDTASZ: //query externalized data size
            case DRDA_CP_QRYROWSET:   //query row set size
            case DRDA_CP_RDBNAM:      //RDB name, as in ACCRDB
            case DRDA_CP_RLSCONV:     //Release Connection
            case DRDA_CP_RTNSQLDA:    //Return SQL Descriptor Area
            case DRDA_CP_SMLDTASZ:    //maximum size of small data
            case DRDA_CP_TYPSQLDA:    //type of SQL descriptor to return
                i_ret = db2_skip_param(p_st_data, ui_param_bd_len, i_whole_flg
                                      , &p_st_fragment->ui_left_ddm_len);
                break;

            /* 取得section number */
            case DRDA_CP_PKGSN:       //RDB package section number
                /* 根据协议长度是16bits, 即是2byte */
                if (ui_param_bd_len != 2)
                {
                    frdbg("EXCSQLSTT: PKGSN parameter length is incorrect!\n");
                    return APM_L7_ANALYZE_FAIL;
                }
                /* 此处的length是bits, 16bit就是2byte */
                i_ret = db2_get_bindr(p_st_data, 2, i_whole_flg, &i64_sess_num
                                     , &p_st_fragment->ui_left_ddm_len);
                /* 设置session number */
                p_st_req->l_cursor_id = (long)i64_sess_num;
                break;

            case DRDA_CP_PKGNAMCSN: //package name, consistency token and section number
                i_ret = db2_get_sess_num(p_st_data, ui_param_bd_len, i_whole_flg
                                        , &p_st_fragment->ui_left_ddm_len
                                        , &i64_sess_num);
                /* 设置session number */
                p_st_req->l_cursor_id = (long)i64_sess_num;
                break;

            default:
                frdbg("OPNQRY: Unkonw parameter!\n");
                return APM_L7_ANALYZE_FAIL;
        }

        /* 判断解析结果 */
        if (i_ret != APM_L7_ANALYZE_SUCC)
        {
            frdbg("OPNQRY: need more data or parse failed!\n");
            return i_ret;
        }
        /* 为取下一个参数做初始化准备 */
        p_st_fragment->i_param_cp = DRDA_CP_NULL;
    }

    /* 设置position */
    p_st_fragment->u64_parsed_index = bytebuff_getPosition(p_st_data);
    /* 跳过OPNQRY的command object */
    while (bytebuff_remaining(p_st_data) > 0)
    {
        /* 取得当前command object的code point */
        i_ret = db2_get_obj_cp(p_st_fragment, i_whole_flg, &i_obj_cp
                              , &p_st_req->ui_ddm_len);
        if (i_ret != APM_L7_ANALYZE_SUCC)
        {
            frdbg("OPNQRY: need more data or parse failed!\n");
            return i_ret;
        }

        /* 跳过该command object */
        switch(i_obj_cp)
        {
            /* OPNQRY的command object解析完了 */
            case DRDA_CP_NULL:
                /* OPNQRY后处理 */
                i_ret = __db2_end_req_cmd(p_st_conn, p_st_hash_report
                                          , p_st_private, DRDA_CP_OPNQRY, -1);
                if (i_ret != APM_L7_ANALYZE_SUCC)
                {
                    frdbg("OPNQRY: add command list failed!\n");
                }
                return i_ret;

            /* 跳过一下object */
            case DRDA_CP_SECTKNOVR:
            case DRDA_CP_EXTDTA:
            case DRDA_CP_TYPDEFOVR:
                i_ret = db2_skip_cmd_obj(p_st_fragment, i_whole_flg);
                break;

            case DRDA_CP_TYPDEFNAM:
                i_ret = db2_get_typdefnam_obj(p_st_private, i_whole_flg
                                             , DB2_OBJ, &p_typdefnam);
                /* 判断解析结果 */
                if (i_ret != APM_L7_ANALYZE_SUCC)
                {
                    frdbg("EXCSQLSTT: need more data or parse failed!\n");
                    return i_ret;
                }

                /* string转换int */
                i_ret = db2_typdef_str2int(p_typdefnam, &p_st_req->i_typdef);
                db2_free((void **)&p_typdefnam);
                if (i_ret != APM_L7_ANALYZE_SUCC)
                {
                    frdbg("EXCSQLSTT: TYPDEFNAM is undefined!\n");
                    return APM_L7_ANALYZE_FAIL;
                }
                break;

            /* 解析sql参数 */
            case DRDA_CP_SQLDTA:
                i_ret = db2_parse_sqldta(p_st_private, i_whole_flg);
                break;

            default:
                frdbg("OPNQRY: Unknow command object!\n");
                return APM_L7_ANALYZE_FAIL;
        }

        /* 解析结果判定 */
        if (i_ret != APM_L7_ANALYZE_SUCC)
        {
            frdbg("OPNQRY: need more data or parse failed!\n");
            return i_ret;
        }

        /* 设置position */
        p_st_fragment->u64_parsed_index = bytebuff_getPosition(p_st_data);
        /* 初始化object command信息 */
        i_obj_cp = DRDA_CP_NULL;
        p_st_fragment->i_obj_cp = DRDA_CP_NULL;
        p_st_fragment->ui_left_obj_len = 0;
    }

    /* 整个request解析完了 */
    if (p_st_fragment->i_correlator_flg == DB2_FALSE || i_whole_flg == DB2_TRUE)
    {
        /* OPNQRY后处理 */
        i_ret = __db2_end_req_cmd(p_st_conn, p_st_hash_report
                                  , p_st_private, DRDA_CP_OPNQRY, -1);
        if (i_ret != APM_L7_ANALYZE_SUCC)
        {
            frdbg("OPNQRY: add command list failed!\n");
        }
        return i_ret;
    }
    else
    {
        return APM_L7_ANALYZE_TODO;
    }
}

/*******************************************************************************
*  FUNC     :  解析CNTQRY
*  ARGS     :  p_st_conn (入力链接信息)
*           :  p_st_hash_report(保存Frreport_data)
*           :  p_st_private(DB2私有数据)
*           :  i_whole_flg(packet是否完整)
*  RTN      :  APM_L7_ANALYZE_SUCC  (success)
*              APM_L7_ANALYZE_TODO  (more data)
*              APM_L7_ANALYZE_FAIL  (failed)
*  NOTE     :
*******************************************************************************/
FR_STATIC int __db2_parse_cntqry(Conntrack *p_st_conn
                             , Frhash_header *p_st_hash_report
                             , L7session_db2_private *p_st_private
                             , int i_whole_flg)
{
    int i_ret = APM_L7_ANALYZE_SUCC;
    int i_obj_cp = 0;
    int i_param_cp = 0;
    int64_t i64_sess_num = 0;
    unsigned int ui_param_bd_len = 0;
    L7_req_db2 *p_st_req = p_st_private->p_st_req;
    L7_fragment_db2 *p_st_fragment = p_st_private->p_st_fragment;
    Frbyte_Packet *p_st_data = p_st_fragment->p_st_data;

    /* 解析CNTQRY command */
    while (p_st_fragment->ui_left_ddm_len)
    {
        i_ret = db2_get_param_hd_info(p_st_fragment, i_whole_flg
                                     , &p_st_fragment->ui_left_ddm_len
                                     , &i_param_cp, &ui_param_bd_len);
        if (i_ret != APM_L7_ANALYZE_SUCC)
        {
            frdbg("CNTQRY: need more data or parse failed!\n");
            return i_ret;
        }

        switch (i_param_cp)
        {
            /* 直接跳过如下参数 */
            case DRDA_CP_CMDSRCID:    //command source identifier
            case DRDA_CP_FREPRVREF:   //Free Previously Returned Progressive References
            case DRDA_CP_MAXBLKEXT:   //maximum number of additional query blocks
            case DRDA_CP_MONITOR:     //monitor events
            case DRDA_CP_QRYBLKRST:   //Query Block Reset
            case DRDA_CP_QRYBLKSZ:    //query block size
            case DRDA_CP_QRYINSID:    //query instance identifier
            case DRDA_CP_QRYROWNBR:   //query row number
            case DRDA_CP_QRYROWSET:   //query row set size
            case DRDA_CP_QRYROWSNS:   //query row sensitivity
            case DRDA_CP_QRYRTNDTA:   //query returns data
            case DRDA_CP_QRYSCRORN:   //query scroll orientation
            case DRDA_CP_RDBNAM:      //RDB name, as in ACCRDB
            case DRDA_CP_RTNEXTDTA:   //Return of EXTDTAOption
                i_ret = db2_skip_param(p_st_data, ui_param_bd_len, i_whole_flg
                                      , &p_st_fragment->ui_left_ddm_len);
                break;

            /* 取得section number */
            case DRDA_CP_PKGSN:       //RDB package section number
                /* 根据协议长度是16bits, 即是2byte */
                if (ui_param_bd_len != 2)
                {
                    frdbg("EXCSQLSTT: PKGSN parameter length is incorrect!\n");
                    return APM_L7_ANALYZE_FAIL;
                }
                /* 此处的length是bits, 16bit就是2byte */
                i_ret = db2_get_bindr(p_st_data, 2, i_whole_flg, &i64_sess_num
                                     , &p_st_fragment->ui_left_ddm_len);
                /* 设置session number */
                p_st_req->l_cursor_id = (long)i64_sess_num;
                break;

            case DRDA_CP_PKGNAMCSN:   //package name, consistency token and section number
                i_ret = db2_get_sess_num(p_st_data, ui_param_bd_len, i_whole_flg
                                        , &p_st_fragment->ui_left_ddm_len
                                        , &i64_sess_num);
                /* 设置session number */
                p_st_req->l_cursor_id = (long)i64_sess_num;
                break;

            default:
                frdbg("CNTQRY: Unkonw parameter!\n");
                return APM_L7_ANALYZE_FAIL;
        }

        /* 判断解析结果 */
        if (i_ret != APM_L7_ANALYZE_SUCC)
        {
            frdbg("CNTQRY: need more data or parse failed!\n");
            return i_ret;
        }
        /* 为取下一个参数做初始化准备 */
        p_st_fragment->i_param_cp = DRDA_CP_NULL;
    }

    /* 设置position */
    p_st_fragment->u64_parsed_index = bytebuff_getPosition(p_st_data);
    /* 跳过CNTQRY的command object */
    while (bytebuff_remaining(p_st_data) > 0)
    {
        /* 取得当前command object的code point */
        i_ret = db2_get_obj_cp(p_st_fragment, i_whole_flg, &i_obj_cp
                              , &p_st_req->ui_ddm_len);
        if (i_ret != APM_L7_ANALYZE_SUCC)
        {
            frdbg("CNTQRY: need more data or parse failed!\n");
            return i_ret;
        }

        /* 跳过该command object */
        switch(i_obj_cp)
        {
            /* OPNQRY的command object解析完了 */
            case DRDA_CP_NULL:
                /* OPNQRY后处理 */
                i_ret = __db2_end_req_cmd(p_st_conn, p_st_hash_report
                                          , p_st_private, DRDA_CP_CNTQRY, -1);
                if (i_ret != APM_L7_ANALYZE_SUCC)
                {
                    frdbg("CNTQRY: add command list failed!\n");
                }
                return i_ret;

            /* 跳过OUTOVR */
            case DRDA_CP_OUTOVR:
                i_ret = db2_skip_cmd_obj(p_st_fragment, i_whole_flg);
                break;

            default:
                frdbg("CNTQRY: Unknow command object!\n");
                return APM_L7_ANALYZE_FAIL;
        }

        /* 解析结果判定 */
        if (i_ret != APM_L7_ANALYZE_SUCC)
        {
            frdbg("CNTQRY: need more data or parse failed!\n");
            return i_ret;
        }

        /* 设置position */
        p_st_fragment->u64_parsed_index = bytebuff_getPosition(p_st_data);
        /* 初始化object command信息 */
        i_obj_cp = DRDA_CP_NULL;
        p_st_fragment->i_obj_cp = DRDA_CP_NULL;
        p_st_fragment->ui_left_obj_len = 0;
    }

    /* 整个request解析完了 */
    if (p_st_fragment->i_correlator_flg == DB2_FALSE || i_whole_flg == DB2_TRUE)
    {
        /* CNTQRY后处理 */
        i_ret = __db2_end_req_cmd(p_st_conn, p_st_hash_report
                                  , p_st_private, DRDA_CP_CNTQRY, -1);
        if (i_ret != APM_L7_ANALYZE_SUCC)
        {
            frdbg("CNTQRY: add command list failed!\n");
        }
        return i_ret;
    }
    else
    {
        return APM_L7_ANALYZE_TODO;
    }
}

/*******************************************************************************
*  FUNC     :  解析CLSQRY
*  ARGS     :  p_st_conn (入力链接信息)
*           :  p_st_hash_report(保存Frreport_data)
*           :  p_st_private(DB2私有数据)
*           :  i_whole_flg(packet是否完整)
*  RTN      :  APM_L7_ANALYZE_SUCC  (success)
*              APM_L7_ANALYZE_TODO  (more data)
*              APM_L7_ANALYZE_FAIL  (failed)
*  NOTE     :
*******************************************************************************/
FR_STATIC int __db2_parse_clsqry(Conntrack *p_st_conn
                             , Frhash_header *p_st_hash_report
                             , L7session_db2_private *p_st_private
                             , int i_whole_flg)
{
    int i_ret = APM_L7_ANALYZE_SUCC;
    int i_param_cp = 0;
    int64_t i64_sess_num = 0;
    unsigned int ui_param_bd_len = 0;
    L7_req_db2 *p_st_req = p_st_private->p_st_req;
    L7_fragment_db2 *p_st_fragment = p_st_private->p_st_fragment;
    Frbyte_Packet *p_st_data = p_st_fragment->p_st_data;

    /*
    * 1.根据IBM官方协议说明, EXCSAT没有command data objects
    */
    if (p_st_fragment->i_correlator_flg == DB2_TRUE)
    {
        frdbg("CLSQRY format is incorrect!\n");
        return APM_L7_ANALYZE_FAIL;
    }

    /* 解析参数 */
    while (p_st_fragment->ui_left_ddm_len)
    {
        i_ret = db2_get_param_hd_info(p_st_fragment, i_whole_flg
                                     , &p_st_fragment->ui_left_ddm_len
                                     , &i_param_cp, &ui_param_bd_len);
        if (i_ret != APM_L7_ANALYZE_SUCC)
        {
            frdbg("CLSQRY: need more data or parse failed!\n");
            return i_ret;
        }

        switch (i_param_cp)
        {
            /* 直接跳过以下参数 */
            case DRDA_CP_RDBNAM:    //RDB name, as in ACCRDB
            case DRDA_CP_MONITOR:   //monitor events
            case DRDA_CP_CMDSRCID:  //command source identifier
            case DRDA_CP_QRYINSID:  //query instance identifier
            case DRDA_CP_QRYCLSRLS: //query close lock release
                i_ret = db2_skip_param(p_st_data, ui_param_bd_len, i_whole_flg
                                      , &p_st_fragment->ui_left_ddm_len);
                break;

            /* 取得section number */
            case DRDA_CP_PKGSN:     //RDB package section number
                /* 根据协议长度是16bits, 即是2byte */
                if (ui_param_bd_len != 2)
                {
                    frdbg("EXCSQLSTT: PKGSN parameter length is incorrect!\n");
                    return APM_L7_ANALYZE_FAIL;
                }
                /* 此处的length是bits, 16bit就是2byte */
                i_ret = db2_get_bindr(p_st_data, 2, i_whole_flg, &i64_sess_num
                                     , &p_st_fragment->ui_left_ddm_len);
                /* 设置session number */
                p_st_req->l_cursor_id = (long)i64_sess_num;
                break;

            case DRDA_CP_PKGNAMCSN: //package name, consistency token, and section number
                i_ret = db2_get_sess_num(p_st_data, ui_param_bd_len, i_whole_flg
                                        , &p_st_fragment->ui_left_ddm_len
                                        , &i64_sess_num);
                /* 设置session number */
                p_st_req->l_cursor_id = (long)i64_sess_num;
                break;

            default:
                frdbg("CLSQRY: unkonw parameter code point!\n");
                return APM_L7_ANALYZE_FAIL;
        }

        /* 判断解析结果 */
        if (i_ret != APM_L7_ANALYZE_SUCC)
        {
            frdbg("CLSQRY: need more data or skip parameter failed!\n");
            return i_ret;
        }
        /* 为取下一个参数做初始化准备 */
        p_st_fragment->i_param_cp = DRDA_CP_NULL;
    }

    /* CLSQRY的后处理 */
    i_ret = __db2_end_req_cmd(p_st_conn, p_st_hash_report
                              , p_st_private, DRDA_CP_CLSQRY, -1);
    if (i_ret != APM_L7_ANALYZE_SUCC)
    {
        frdbg("CLSQRY: add command list failed!\n");
    }
    /* 设置position */
    p_st_fragment->u64_parsed_index = bytebuff_getPosition(p_st_data);
    return i_ret;
}

/*******************************************************************************
*  FUNC     :  解析RDBCMM
*  ARGS     :  p_st_conn (入力链接信息)
*           :  p_st_hash_report(保存Frreport_data)
*           :  p_st_private(DB2私有数据)
*           :  i_whole_flg(packet是否完整)
*  RTN      :  APM_L7_ANALYZE_SUCC  (success)
*              APM_L7_ANALYZE_TODO  (more data)
*              APM_L7_ANALYZE_FAIL  (failed)
*  NOTE     :
*******************************************************************************/
FR_STATIC int __db2_parse_rdbcmm(Conntrack *p_st_conn
                             , Frhash_header *p_st_hash_report
                             , L7session_db2_private *p_st_private
                             , int i_whole_flg)
{
    int i_ret = APM_L7_ANALYZE_SUCC;
    L7_fragment_db2 *p_st_fragment = p_st_private->p_st_fragment;

    /*
    * 1.根据IBM官方协议说明, RDBCMM没有command data objects
    */
    if (p_st_fragment->i_correlator_flg == DB2_TRUE)
    {
        frdbg("RDBCMM format is incorrect!\n");
        return APM_L7_ANALYZE_FAIL;
    }

    /* 忽略RDBCMM及其command object */
    i_ret = db2_skip_ddm(p_st_fragment, i_whole_flg);
    if (i_ret != APM_L7_ANALYZE_SUCC)
    {
        frdbg("RDBCMM: need more data or parse failed!\n");
        return i_ret;
    }

    /* RDBCMM的后处理 */
    i_ret = __db2_end_req_cmd(p_st_conn, p_st_hash_report
                              , p_st_private, DRDA_CP_RDBCMM, -1);
    if (i_ret != APM_L7_ANALYZE_SUCC)
    {
        frdbg("RDBCMM: add command list failed!\n");
    }
    /* 设置position */
    p_st_fragment->u64_parsed_index = bytebuff_getPosition(p_st_fragment->p_st_data);
    return i_ret;
}

/*******************************************************************************
*  FUNC     :  解析RDBRLLBCK
*  ARGS     :  p_st_conn (入力链接信息)
*           :  p_st_hash_report(保存Frreport_data)
*           :  p_st_private(DB2私有数据)
*           :  i_whole_flg(packet是否完整)
*  RTN      :  APM_L7_ANALYZE_SUCC  (success)
*              APM_L7_ANALYZE_TODO  (more data)
*              APM_L7_ANALYZE_FAIL  (failed)
*  NOTE     :
*******************************************************************************/
FR_STATIC int __db2_parse_rdbrllbck(Conntrack *p_st_conn
                                 , Frhash_header *p_st_hash_report
                                 , L7session_db2_private *p_st_private
                                 , int i_whole_flg)
{
    int i_ret = APM_L7_ANALYZE_SUCC;
    L7_fragment_db2 *p_st_fragment = p_st_private->p_st_fragment;

    /*
    * 1.根据IBM官方协议说明, RDBRLLBCK没有command data objects
    */
    if (p_st_fragment->i_correlator_flg == DB2_TRUE)
    {
        frdbg("RDBRLLBCK format is incorrect!\n");
        return APM_L7_ANALYZE_FAIL;
    }

    /* 忽略EXCSQLSET及其command object */
    i_ret = db2_skip_ddm(p_st_fragment, i_whole_flg);
    if (i_ret != APM_L7_ANALYZE_SUCC)
    {
        frdbg("RDBRLLBCK: need more data or parse failed!\n");
        return i_ret;
    }

    /* RDBRLLBCK的后处理 */
    i_ret = __db2_end_req_cmd(p_st_conn, p_st_hash_report
                              , p_st_private, DRDA_CP_RDBRLLBCK, -1);
    if (i_ret != APM_L7_ANALYZE_SUCC)
    {
        frdbg("RDBRLLBCK: add command list failed!\n");
    }
    /* 设置position */
    p_st_fragment->u64_parsed_index = bytebuff_getPosition(p_st_fragment->p_st_data);
    return i_ret;
}

/*******************************************************************************
*  FUNC     :  解析EXCSQLIMM
*  ARGS     :  p_st_private (DB2私有数据)
*           :  i_whole_flg(packet是否完整)
*  RTN      :  APM_L7_ANALYZE_SUCC  (success)
*              APM_L7_ANALYZE_TODO  (more data)
*              APM_L7_ANALYZE_FAIL  (failed)
*  NOTE     :
*******************************************************************************/
FR_STATIC int __db2_parse_excsqlimm(Conntrack *p_st_conn
                                , Frhash_header *p_st_hash_report
                                , L7session_db2_private *p_st_private
                                , int i_whole_flg)
{
    int i_ret = APM_L7_ANALYZE_SUCC;
    int i_obj_cp = 0;
    int i_param_cp = 0;
    int64_t i64_sess_num = 0;
    unsigned int ui_param_bd_len = 0;
    L7_req_db2 *p_st_req = p_st_private->p_st_req;
    L7_fragment_db2 *p_st_fragment = p_st_private->p_st_fragment;
    Frbyte_Packet *p_st_data = p_st_fragment->p_st_data;

    /* 解析EXCSQLIMM command */
    while (p_st_fragment->ui_left_ddm_len)
    {
        i_ret = db2_get_param_hd_info(p_st_fragment, i_whole_flg
                                     , &p_st_fragment->ui_left_ddm_len
                                     , &i_param_cp, &ui_param_bd_len);
        if (i_ret != APM_L7_ANALYZE_SUCC)
        {
            frdbg("EXCSQLIMM: need more data or parse failed!\n");
            return i_ret;
        }

        switch (i_param_cp)
        {
            /* 直接跳过如下参数 */
            case DRDA_CP_CMDSRCID:    //command source identifier
            case DRDA_CP_MONITOR:     //monitor events
            case DRDA_CP_QRYINSID:    //query instance identifier)
            case DRDA_CP_RDBNAM:      //RDB name, as in ACCRDB
            case DRDA_CP_RDBCMTOK:    //RDB Commit Allowed
            case DRDA_CP_RTNSETSTT:   //Return SET Statement
            //case DRDA_CP_PKGSN:       //RDB package section number
            //case DRDA_CP_PKGNAMCSN:   //package name, consistency token and section number
                i_ret = db2_skip_param(p_st_data, ui_param_bd_len, i_whole_flg
                                      , &p_st_fragment->ui_left_ddm_len);
                break;

            /* 取得section number */
            case DRDA_CP_PKGSN:       //RDB package section number
                /* 根据协议长度是16bits, 即是2byte */
                if (ui_param_bd_len != 2)
                {
                    frdbg("EXCSQLSTT: PKGSN parameter length is incorrect!\n");
                    return APM_L7_ANALYZE_FAIL;
                }
                /* 此处的length是bits, 16bit就是2byte */
                i_ret = db2_get_bindr(p_st_data, 2, i_whole_flg, &i64_sess_num
                                     , &p_st_fragment->ui_left_ddm_len);
                /* 设置session number */
                p_st_req->l_cursor_id = (long)i64_sess_num;
                break;

            case DRDA_CP_PKGNAMCSN:   //package name, consistency token and section number
                i_ret = db2_get_sess_num(p_st_data, ui_param_bd_len, i_whole_flg
                                        , &p_st_fragment->ui_left_ddm_len
                                        , &i64_sess_num);
                /* 设置session number */
                p_st_req->l_cursor_id = (long)i64_sess_num;
                break;

            default:
                frdbg("EXCSQLIMM: Unkonw parameter!\n");
                return APM_L7_ANALYZE_FAIL;
        }

        /* 判断解析结果 */
        if (i_ret != APM_L7_ANALYZE_SUCC)
        {
            frdbg("EXCSQLIMM: need more data or parse failed!\n");
            return i_ret;
        }
        /* 为取下一个参数做初始化准备 */
        p_st_fragment->i_param_cp = DRDA_CP_NULL;
    }

    /* 设置position */
    p_st_fragment->u64_parsed_index = bytebuff_getPosition(p_st_data);
    /* 解析EXCSQLIMM的command object */
    while (bytebuff_remaining(p_st_data) > 0)
    {
        /* 取得当前command object的code point */
        i_ret = db2_get_obj_cp(p_st_fragment, i_whole_flg, &i_obj_cp
                              , &p_st_private->p_st_req->ui_ddm_len);
        if (i_ret != APM_L7_ANALYZE_SUCC)
        {
            frdbg("EXCSQLIMM: need more data or parse failed!\n");
            return i_ret;
        }

        /* 跳过该command object */
        switch(i_obj_cp)
        {
            /* EXCSQLIMM的command object解析完了 */
            case DRDA_CP_NULL:
                /* EXCSQLIMM后处理 */
                i_ret = __db2_end_req_cmd(p_st_conn, p_st_hash_report
                                          , p_st_private, DRDA_CP_EXCSQLIMM, -1);
                if (i_ret != APM_L7_ANALYZE_SUCC)
                {
                    frdbg("EXCSQLIMM: add command lsit failed!\n");
                }
                return i_ret;

            /* 跳过以下object */
            case DRDA_CP_SECTKNOVR: //sectkn overrides
            case DRDA_CP_TYPDEFOVR: //data type definition override
            case DRDA_CP_TYPDEFNAM: //data type definition name
            case DRDA_CP_SQLATTR:   //SQL Statement Attributes
                i_ret = db2_skip_cmd_obj(p_st_fragment, i_whole_flg);
                break;

            /* 解析sql语句 */
            case DRDA_CP_SQLSTT:   //SQL statement
                i_ret = db2_get_sqlstt(p_st_fragment, i_whole_flg
                                      , &p_st_req->p_sql);

                break;

            default:
                frdbg("EXCSQLIMM: Unknow command object!\n");
                return APM_L7_ANALYZE_FAIL;
        }

        /* 解析结果判定 */
        if (i_ret != APM_L7_ANALYZE_SUCC)
        {
            frdbg("EXCSQLIMM: need more data or parse failed!\n");
            return i_ret;
        }

        /* 设置position */
        p_st_fragment->u64_parsed_index = bytebuff_getPosition(p_st_data);
        /* 初始化object command信息 */
        i_obj_cp = DRDA_CP_NULL;
        p_st_fragment->i_obj_cp = DRDA_CP_NULL;
        p_st_fragment->ui_left_obj_len = 0;
    }

    /* 整个request解析完了 */
    if (p_st_fragment->i_correlator_flg == DB2_FALSE || i_whole_flg == DB2_TRUE)
    {
        /* EXCSQLIMM后处理 */
        i_ret = __db2_end_req_cmd(p_st_conn, p_st_hash_report
                                  , p_st_private, DRDA_CP_EXCSQLIMM, -1);
        if (i_ret != APM_L7_ANALYZE_SUCC)
        {
            frdbg("EXCSQLIMM: add command lsit failed!\n");
        }
        return i_ret;
    }
    else
    {
        return APM_L7_ANALYZE_TODO;
    }
}

/*******************************************************************************
*  FUNC     :  解析DSCSQLSTT
*  ARGS     :  p_st_private (DB2私有数据)
*           :  i_whole_flg(packet是否完整)
*  RTN      :  APM_L7_ANALYZE_SUCC  (success)
*              APM_L7_ANALYZE_TODO  (more data)
*              APM_L7_ANALYZE_FAIL  (failed)
*  NOTE     :
*******************************************************************************/
FR_STATIC int __db2_parse_dscsqlstt(Conntrack *p_st_conn
                                , Frhash_header *p_st_hash_report
                                , L7session_db2_private *p_st_private
                                , int i_whole_flg)
{
    int i_ret = APM_L7_ANALYZE_SUCC;
    int i_param_cp = 0;
    int64_t i64_sess_num = 0;
    unsigned int ui_param_bd_len = 0;
    L7_req_db2 *p_st_req = p_st_private->p_st_req;
    L7_fragment_db2 *p_st_fragment = p_st_private->p_st_fragment;
    Frbyte_Packet *p_st_data = p_st_fragment->p_st_data;

    /*
    * 1.根据IBM官方协议说明, DSCSQLSTT没有command data objects
    */
    if (p_st_fragment->i_correlator_flg == DB2_TRUE)
    {
        frdbg("DSCSQLSTT format is incorrect!\n");
        return APM_L7_ANALYZE_FAIL;
    }

    /* 解析参数 */
    while (p_st_fragment->ui_left_ddm_len)
    {
        i_ret = db2_get_param_hd_info(p_st_fragment, i_whole_flg
                                     , &p_st_fragment->ui_left_ddm_len
                                     , &i_param_cp, &ui_param_bd_len);
        if (i_ret != APM_L7_ANALYZE_SUCC)
        {
            frdbg("DSCSQLSTT: need more data or parse failed!\n");
            return i_ret;
        }

        switch (i_param_cp)
        {
            /* 直接跳过以下参数 */
            case DRDA_CP_CMDSRCID:  //command source identifier
            case DRDA_CP_MONITOR:   //monitor events
            case DRDA_CP_QRYINSID:  //query instance identifier
            case DRDA_CP_RDBNAM:    //RDB name, as in ACCRDB
            case DRDA_CP_TYPSQLDA:  //type of descriptor to return
                i_ret = db2_skip_param(p_st_data, ui_param_bd_len, i_whole_flg
                                      , &p_st_fragment->ui_left_ddm_len);
                break;

            /* 取得section number */
            case DRDA_CP_PKGSN:     //RDB package section number
                /* 根据协议长度是16bits, 即是2byte */
                if (ui_param_bd_len != 2)
                {
                    frdbg("EXCSQLSTT: PKGSN parameter length is incorrect!\n");
                    return APM_L7_ANALYZE_FAIL;
                }
                /* 此处的length是bits, 16bit就是2byte */
                i_ret = db2_get_bindr(p_st_data, 2, i_whole_flg, &i64_sess_num
                                     , &p_st_fragment->ui_left_ddm_len);
                /* 设置session number */
                p_st_req->l_cursor_id = (long)i64_sess_num;
                break;

            case DRDA_CP_PKGNAMCSN: //package name, consistency token, and section number
                i_ret = db2_get_sess_num(p_st_data, ui_param_bd_len, i_whole_flg
                                         , &p_st_fragment->ui_left_ddm_len
                                         , &i64_sess_num);
                /* 设置session numr */
                p_st_req->l_cursor_id = (long)i64_sess_num;
                break;

            default:
                frdbg("DSCSQLSTT: unkonw parameter code point!\n");
                return APM_L7_ANALYZE_FAIL;
        }

        /* 判断解析结果 */
        if (i_ret != APM_L7_ANALYZE_SUCC)
        {
            frdbg("DSCSQLSTT: need more data or skip parameter failed!\n");
            return i_ret;
        }
        /* 为取下一个参数做初始化准备 */
        p_st_fragment->i_param_cp = DRDA_CP_NULL;
    }

    /* 设置position */
    p_st_fragment->u64_parsed_index = bytebuff_getPosition(p_st_data);
    /* DSCSQLSTT的后处理 */
    i_ret = __db2_end_req_cmd(p_st_conn, p_st_hash_report
                              , p_st_private, DRDA_CP_DSCSQLSTT, -1);
    if (i_ret != APM_L7_ANALYZE_SUCC)
    {
        frdbg("DSCSQLSTT: add command list failed!\n");
    }
    return i_ret;
}

/*******************************************************************************
*  FUNC     :  解析EXCSQLSTT
*  ARGS     :  p_st_private (DB2私有数据)
*           :  i_whole_flg(packet是否完整)
*  RTN      :  APM_L7_ANALYZE_SUCC  (success)
*              APM_L7_ANALYZE_TODO  (more data)
*              APM_L7_ANALYZE_FAIL  (failed)
*  NOTE     :
*******************************************************************************/
FR_STATIC int __db2_parse_excsqlstt(Conntrack *p_st_conn
                                , Frhash_header *p_st_hash_report
                                , L7session_db2_private *p_st_private
                                , int i_whole_flg)
{
    int i_ret = APM_L7_ANALYZE_SUCC;
    int i_obj_cp = 0;
    int i_param_cp = 0;
    int64_t i64_sess_num = 0;
    unsigned int ui_param_bd_len = 0;
    char *p_typdefnam = NULL;
    L7_req_db2 *p_st_req = p_st_private->p_st_req;
    L7_fragment_db2 *p_st_fragment = p_st_private->p_st_fragment;
    Frbyte_Packet *p_st_data = p_st_fragment->p_st_data;

    /* 解析EXCSQLSTT command */
    while (p_st_fragment->ui_left_ddm_len)
    {
        i_ret = db2_get_param_hd_info(p_st_fragment, i_whole_flg
                                     , &p_st_fragment->ui_left_ddm_len
                                     , &i_param_cp, &ui_param_bd_len);
        if (i_ret != APM_L7_ANALYZE_SUCC)
        {
            frdbg("EXCSQLSTT: need more data or parse failed!\n");
            return i_ret;
        }

        switch (i_param_cp)
        {
            /* 直接跳过以下参数 */
            case DRDA_CP_ATMIND:      //Atomicity Indicator
            case DRDA_CP_CMDSRCID:    //command source identifier
            case DRDA_CP_DYNDTAFMT:   //dynamic data format
            case DRDA_CP_DFTFMTXML:   //Default Format for XML Data
            case DRDA_CP_MAXBLKEXT:   //maximum number of additional query blocks
            case DRDA_CP_MAXRSLCNT:   //maximum number of result sets
            case DRDA_CP_MEDDTASZ:    //maximum size of medium data
            case DRDA_CP_MONITOR:     //monitor events
            case DRDA_CP_NBRROW:      //Number of Input Rows
            case DRDA_CP_OUTEXP:      //output expected
            case DRDA_CP_OUTOVRXML:   //Output Option for XML Data
            case DRDA_CP_OUTOVROPT:   //output option
            case DRDA_CP_RDBNAM:      //RDB name, as in ACCRDB
            case DRDA_CP_PRCNAM:      //stored procedure name
            case DRDA_CP_QRYBLKSZ:    //query block size
            case DRDA_CP_QRYEXTDTASZ: //query externalized data size
            case DRDA_CP_QRYINSID:    //query instance identifier
            case DRDA_CP_QRYROWSET:   //query row set size)
            case DRDA_CP_RDBCMTOK:    //RDB commit by application server allowed
            case DRDA_CP_RTNSETSTT:   //Return SET Statement
            case DRDA_CP_RTNSQLDA:    //Return SQL Descriptor Area
            case DRDA_CP_RSLSETFLG:   //result set flags
            case DRDA_CP_SMLDTASZ:    //maximum size of small data
            case DRDA_CP_TYPSQLDA:    //type of SQL descriptor to return
                i_ret = db2_skip_param(p_st_data, ui_param_bd_len, i_whole_flg
                                      , &p_st_fragment->ui_left_ddm_len);
                break;

            /* 取得section number */
            case DRDA_CP_PKGSN:       //RDB package section number
                /* 根据协议长度是16bits, 即是2byte */
                if (ui_param_bd_len != 2)
                {
                    frdbg("EXCSQLSTT: PKGSN parameter length is incorrect!\n");
                    return APM_L7_ANALYZE_FAIL;
                }
                /* 此处的length是bits, 16bit就是2byte */
                i_ret = db2_get_bindr(p_st_data, 2, i_whole_flg, &i64_sess_num
                                     , &p_st_fragment->ui_left_ddm_len);
                /* 设置session number */
                p_st_req->l_cursor_id = (long)i64_sess_num;
                break;

            case DRDA_CP_PKGNAMCSN:   //package name, consistency token and section number
                i_ret = db2_get_sess_num(p_st_data, ui_param_bd_len, i_whole_flg
                                        , &p_st_fragment->ui_left_ddm_len
                                        , &i64_sess_num);
                /* 设置session number */
                p_st_req->l_cursor_id = (long)i64_sess_num;
                break;

            default:
                frdbg("EXCSQLSTT: Unkonw parameter!\n");
                return APM_L7_ANALYZE_FAIL;
        }

        /* 判断解析结果 */
        if (i_ret != APM_L7_ANALYZE_SUCC)
        {
            frdbg("EXCSQLSTT: need more data or parse failed!\n");
            return i_ret;
        }
        /* 为取下一个参数做初始化准备 */
        p_st_fragment->i_param_cp = DRDA_CP_NULL;
    }

    /* 设置position */
    p_st_fragment->u64_parsed_index = bytebuff_getPosition(p_st_data);
    /* 解析EXCSQLSTT的command object */
    while (bytebuff_remaining(p_st_data) > 0)
    {
        /* 取得当前command object的code point */
        i_ret = db2_get_obj_cp(p_st_fragment, i_whole_flg, &i_obj_cp
                              , &p_st_private->p_st_req->ui_ddm_len);
        if (i_ret != APM_L7_ANALYZE_SUCC)
        {
            frdbg("EXCSQLSTT: need more data or parse failed!\n");
            return i_ret;
        }

        /* 跳过该command object */
        switch(i_obj_cp)
        {
            /* EXCSQLIMM的command object解析完了 */
            case DRDA_CP_NULL:
                /* EXCSQLSTT后处理 */
                i_ret = __db2_end_req_cmd(p_st_conn, p_st_hash_report
                                          , p_st_private, DRDA_CP_EXCSQLSTT, -1);
                if (i_ret != APM_L7_ANALYZE_SUCC)
                {
                    frdbg("EXCSQLSTT: add command list failed!\n");
                }
                return i_ret;

            /* 跳过以下object */
            case DRDA_CP_EXTDTA:
            case DRDA_CP_OUTOVR:
            case DRDA_CP_PRCNAM:
            case DRDA_CP_SECTKNOVR:
            case DRDA_CP_TYPDEFOVR:
                i_ret = db2_skip_cmd_obj(p_st_fragment, i_whole_flg);
                break;

            case DRDA_CP_TYPDEFNAM:
                i_ret = db2_get_typdefnam_obj(p_st_private, i_whole_flg
                                             , DB2_OBJ, &p_typdefnam);
                /* 判断解析结果 */
                if (i_ret != APM_L7_ANALYZE_SUCC)
                {
                    frdbg("EXCSQLSTT: need more data or parse failed!\n");
                    return i_ret;
                }

                /* string转换int */
                i_ret = db2_typdef_str2int(p_typdefnam, &p_st_req->i_typdef);
                db2_free((void **)&p_typdefnam);
                if (i_ret != APM_L7_ANALYZE_SUCC)
                {
                    frdbg("EXCSQLSTT: TYPDEFNAM is undefined!\n");
                    return APM_L7_ANALYZE_FAIL;
                }
                break;

            /* 解析sql参数 */
            case DRDA_CP_SQLDTA:   //SQL参数
                i_ret = db2_parse_sqldta(p_st_private, i_whole_flg);
                break;

            default:
                frdbg("EXCSQLSTT: Unknow command object!\n");
                return APM_L7_ANALYZE_FAIL;
        }

        /* 结果判定 */
        if (i_ret != APM_L7_ANALYZE_SUCC)
        {
            frdbg("EXCSQLSTT: need more data or parse failed!\n");
            return i_ret;
        }

        /* 设置position */
        p_st_fragment->u64_parsed_index = bytebuff_getPosition(p_st_data);
        /* 初始化object command信息 */
        i_obj_cp = DRDA_CP_NULL;
        p_st_fragment->i_obj_cp = DRDA_CP_NULL;
        p_st_fragment->ui_left_obj_len = 0;
    }

    /* 整个request解析完了 */
    if (p_st_fragment->i_correlator_flg == DB2_FALSE || i_whole_flg == DB2_TRUE)
    {
        /* EXCSQLSTT后处理 */
        i_ret = __db2_end_req_cmd(p_st_conn, p_st_hash_report
                                  , p_st_private, DRDA_CP_EXCSQLSTT, -1);
        if (i_ret != APM_L7_ANALYZE_SUCC)
        {
            frdbg("EXCSQLSTT: add command list failed!\n");
        }
        return i_ret;
    }
    else
    {
        return APM_L7_ANALYZE_TODO;
    }
}

/*******************************************************************************
*  FUNC     :  跳过C004
*  ARGS     :  p_st_conn (入力链接信息)
*           :  p_st_hash_report(保存Frreport_data)
*           :  p_st_private(DB2私有数据)
*           :  i_whole_flg(packet是否完整)
*  RTN      :  APM_L7_ANALYZE_SUCC  (success)
*              APM_L7_ANALYZE_TODO  (more data)
*              APM_L7_ANALYZE_FAIL  (failed)
*  NOTE     :
*******************************************************************************/
FR_STATIC int __db2_parse_c004(Conntrack *p_st_conn
                             , Frhash_header *p_st_hash_report
                             , L7session_db2_private *p_st_private
                             , int i_whole_flg)
{
    int i_ret = APM_L7_ANALYZE_SUCC;
    int i_obj_cp = DRDA_CP_NULL;
    L7_fragment_db2 *p_st_fragment = p_st_private->p_st_fragment;
    Frbyte_Packet *p_st_data = p_st_fragment->p_st_data;

    /* 忽略C004及其command object */
    i_ret = db2_skip_ddm(p_st_fragment, i_whole_flg);
    if (i_ret != APM_L7_ANALYZE_SUCC)
    {
        frdbg("C004: need more data or parse failed!\n");
        return i_ret;
    }
    /* 为取下一个参数做初始化准备 */
    p_st_fragment->i_param_cp = DRDA_CP_NULL;

    /* 设置position */
    p_st_fragment->u64_parsed_index = bytebuff_getPosition(p_st_data);
    /* 解析EXCSQLSTT的command object */
    while (bytebuff_remaining(p_st_data) > 0)
    {
        /* 取得当前command object的code point */
        i_ret = db2_get_obj_cp(p_st_fragment, i_whole_flg, &i_obj_cp
                              , &p_st_private->p_st_req->ui_ddm_len);
        if (i_ret != APM_L7_ANALYZE_SUCC)
        {
            frdbg("C004 object: need more data or parse failed!\n");
            return i_ret;
        }
        i_ret = db2_skip_cmd_obj(p_st_fragment, i_whole_flg);
        if (i_ret != APM_L7_ANALYZE_SUCC)
        {
            frdbg("C004 object: need more data or parse failed!\n");
            return i_ret;
        }
        /* 设置position */
        p_st_fragment->u64_parsed_index = bytebuff_getPosition(p_st_data);
        /* 初始化object command信息 */
        i_obj_cp = DRDA_CP_NULL;
        p_st_fragment->i_obj_cp = DRDA_CP_NULL;
        p_st_fragment->ui_left_obj_len = 0;
    }

    return i_ret;
}

/*******************************************************************************
*  FUNC     :  解析SYNCCTL
*  ARGS     :  p_st_conn (入力链接信息)
*           :  p_st_hash_report(保存Frreport_data)
*           :  p_st_private(DB2私有数据)
*           :  i_whole_flg(packet是否完整)
*  RTN      :  APM_L7_ANALYZE_SUCC  (success)
*              APM_L7_ANALYZE_TODO  (more data)
*              APM_L7_ANALYZE_FAIL  (failed)
*  NOTE     :
*******************************************************************************/
FR_STATIC int __db2_parse_syncctl(Conntrack *p_st_conn
                                , Frhash_header *p_st_hash_report
                                , L7session_db2_private *p_st_private
                                , int i_whole_flg)
{
    int i_ret = APM_L7_ANALYZE_SUCC;
    int i_obj_cp = 0;
    int i_param_cp = 0;
    uint8_t u8_syntype = 0;
    unsigned int ui_param_bd_len = 0;
    L7_fragment_db2 *p_st_fragment = p_st_private->p_st_fragment;
    Frbyte_Packet *p_st_data = p_st_fragment->p_st_data;

    /* 解析参数 */
    while (p_st_fragment->ui_left_ddm_len)
    {
        i_ret = db2_get_param_hd_info(p_st_fragment, i_whole_flg
                                     , &p_st_fragment->ui_left_ddm_len
                                     , &i_param_cp, &ui_param_bd_len);
        if (i_ret != APM_L7_ANALYZE_SUCC)
        {
            frdbg("SYNCCTL: need more data or parse failed!\n");
            return i_ret;
        }

        switch (i_param_cp)
        {
            /* 直接跳过如下参数 */
            case DRDA_CP_FORGET:          //Forget Unit of Work  0x1186
            case DRDA_CP_RLSCONV:         //Release Conversation 0x119F
            case DRDA_CP_TIMEOUT:         //Time Out 0x1907
            case DRDA_CP_UOWID:           //Unit ofWork Identifier 0x11AA
            case DRDA_CP_XAFLAGS:         //XA Flags 0x1903
            case DRDA_CP_XIDSHR:          //Share Recoverable Resources 0x1802
            case DRDA_CP_XID:             //Global Transaction Identifier 0x1801
                i_ret = db2_skip_param(p_st_data, ui_param_bd_len, i_whole_flg
                                      , &p_st_fragment->ui_left_ddm_len);
                break;

            /* 取得Sync Point Operation Type */
            case DRDA_CP_SYNCTYPE:        //Sync Point Operation Type 0x1187
                /* 根据协议长度是1byte */
                if (ui_param_bd_len != 1)
                {
                    frdbg("SYNCCTL: SYNCTYPE parameter length is incorrect!\n");
                    return APM_L7_ANALYZE_FAIL;
                }
                i_ret = db2_get_synctype(p_st_data, ui_param_bd_len, i_whole_flg, &u8_syntype
                                      , &p_st_fragment->ui_left_ddm_len);
                break;

            default:
                frdbg("SYNCCTL: Unkonw parameter!\n");
                return APM_L7_ANALYZE_FAIL;
        }

        /* 判断解析结果 */
        if (i_ret != APM_L7_ANALYZE_SUCC)
        {
            frdbg("SYNCCTL: need more data or parse failed!\n");
            return i_ret;
        }
        /* 为取下一个参数做初始化准备 */
        p_st_fragment->i_param_cp = DRDA_CP_NULL;
    }

    /* 设置position */
    p_st_fragment->u64_parsed_index = bytebuff_getPosition(p_st_data);
    /* 解析SYNCCTL的command object */
    while (bytebuff_remaining(p_st_data) > 0)
    {
        /* 取得当前command object的code point */
        i_ret = db2_get_obj_cp(p_st_fragment, i_whole_flg, &i_obj_cp
                              , &p_st_private->p_st_req->ui_ddm_len);
        if (i_ret != APM_L7_ANALYZE_SUCC)
        {
            frdbg("SYNCCTL: need more data or parse failed!\n");
            return i_ret;
        }

        /* 跳过该command object */
        switch(i_obj_cp)
        {
            /* SYNCCTL的command object解析完了 */
            case DRDA_CP_NULL:
                /* SYNCCTL的后处理 */
                i_ret = __db2_end_req_cmd(p_st_conn, p_st_hash_report
                                          , p_st_private, DRDA_CP_SYNCCTL, u8_syntype);
                if (i_ret != APM_L7_ANALYZE_SUCC)
                {
                    frdbg("SYNCCTL: add command list failed!\n");
                }
                return i_ret;

            /* 跳过正常的SYNCLOG */
            case DRDA_CP_SYNCLOG:   // Sync Point Log
                i_ret = db2_skip_cmd_obj(p_st_fragment, i_whole_flg);
                break;

            default:
                frdbg("SYNCCTL: Unknow command object!\n");
                return APM_L7_ANALYZE_FAIL;
        }

        /* 解析结果判定 */
        if (i_ret != APM_L7_ANALYZE_SUCC)
        {
            frdbg("SYNCCTL: need more data or parse failed!\n");
            return i_ret;
        }

        /* 设置position */
        p_st_fragment->u64_parsed_index = bytebuff_getPosition(p_st_data);
        /* 初始化object command信息 */
        i_obj_cp = DRDA_CP_NULL;
        p_st_fragment->i_obj_cp = DRDA_CP_NULL;
        p_st_fragment->ui_left_obj_len = 0;
    }

    /* 整个request解析完了 */
    if (p_st_fragment->i_correlator_flg == DB2_FALSE || i_whole_flg == DB2_TRUE)
    {
        /* SYNCCTL后处理 */
        i_ret = __db2_end_req_cmd(p_st_conn, p_st_hash_report
                                 , p_st_private, DRDA_CP_SYNCCTL, u8_syntype);
        if (i_ret != APM_L7_ANALYZE_SUCC)
        {
            frdbg("SYNCCTL: add command list failed!\n");
        }
        return i_ret;
    }
    else
    {
        return APM_L7_ANALYZE_TODO;
    }
}

/*******************************************************************************
*  FUNC     :  解析request
*  ARGS     :  p_st_conn (入力链接信息)
*           :  p_st_hash_report(Frreport_data)
*           :  p_st_private(DB2私有数据)
*           :  i_whole_flg(packe是否完整标识)
*  RTN      :  参照module.h
*  NOTE     :
*******************************************************************************/
int db2_parse_request(Conntrack *p_st_conn
                     , Frhash_header *p_st_hash_report
                     , L7session_db2_private *p_st_private
                     , int i_whole_flg)
{
    int i_ret = APM_L7_ANALYZE_SUCC;
    int i_sub_ret = APM_L7_ANALYZE_SUCC;
    int i_req_cp = DRDA_CP_NULL;
    L7_fragment_db2 *p_st_fragment = p_st_private->p_st_fragment;
    Frbyte_Packet *p_st_data = p_st_fragment->p_st_data;

    /* request为NULL时创建 */
    if (p_st_private->p_st_req == NULL)
    {
        p_st_private->p_st_req = db2_create_request();
        if (p_st_private->p_st_req == NULL)
        {
            frdbg("Create request failed\n");
            return APM_L7_ANALYZE_FAIL;
        }
    }
    else
    {
        /* 若是上一次request解析完了, 此次又是request数据 */
        if (p_st_private->p_st_req->i_need_req_resp == DB2_RESPONSE)
        {
            /* 销毁上次的request数据 */
            db2_destroy_request(&(p_st_private->p_st_req));
            /* 新建request */
            p_st_private->p_st_req = db2_create_request();
            if (p_st_private->p_st_req == NULL)
            {
                frdbg("Recreate quest failed\n");
                return APM_L7_ANALYZE_FAIL;
            }
        }
    }

    /* 将位置设置到上次解析正确的位置 */
    bytebuff_setPosition(p_st_data, p_st_fragment->u64_parsed_index);
    while (bytebuff_remaining(p_st_data) > 0)
    {
        /* 取得当前request comamnd的code point */
        i_ret = db2_get_ddm_cp(p_st_fragment, i_whole_flg, &i_req_cp
                               , &p_st_private->p_st_req->ui_ddm_len);
        if (i_ret != APM_L7_ANALYZE_SUCC)
        {
            frdbg("REQUEST: Need more data or parse failed!\n");
            return i_ret;
        }

        /* 根据CODE POINT解析DDM */
        switch (i_req_cp)
        {
            case DRDA_CP_EXCSAT:
                //frdbg("__db2_parse_excsat\n");
                i_ret = __db2_parse_excsat(p_st_conn, p_st_hash_report
                                          , p_st_private, i_whole_flg);
                break;

            case DRDA_CP_ACCSEC:
                //frdbg("__db2_parse_accsec\n");
                i_ret = __db2_parse_accsec(p_st_conn, p_st_hash_report
                                          , p_st_private, i_whole_flg);
                break;

            case DRDA_CP_SECCHK:
                //frdbg("__db2_parse_secchk\n");
                i_ret = __db2_parse_secchk(p_st_conn, p_st_hash_report
                                          , p_st_private, i_whole_flg);
                break;

            case DRDA_CP_ACCRDB:
                //frdbg("__db2_parse_accrdb\n");
                i_ret = __db2_parse_accrdb(p_st_conn, p_st_hash_report
                                          , p_st_private, i_whole_flg);
                break;

            case DRDA_CP_EXCSQLSET:
                //frdbg("__db2_parse_excsqlset\n");
                i_ret = __db2_parse_excsqlset(p_st_conn, p_st_hash_report
                                             , p_st_private, i_whole_flg);
                break;

            case DRDA_CP_PRPSQLSTT:
                //frdbg("__db2_parse_prpsqlstt\n");
                i_ret = __db2_parse_prpsqlstt(p_st_conn, p_st_hash_report
                                             , p_st_private, i_whole_flg);
                break;

            case DRDA_CP_OPNQRY:
                //frdbg("__db2_parse_opnqry\n");
                i_ret = __db2_parse_opnqry(p_st_conn, p_st_hash_report
                                          , p_st_private, i_whole_flg);
                break;

            case DRDA_CP_CNTQRY:
                //frdbg("__db2_parse_cntqry\n");
                i_ret = __db2_parse_cntqry(p_st_conn, p_st_hash_report
                                          , p_st_private, i_whole_flg);
                break;

            case DRDA_CP_CLSQRY:
                //frdbg("__db2_parse_clsqry\n");
                i_ret = __db2_parse_clsqry(p_st_conn, p_st_hash_report
                                          , p_st_private, i_whole_flg);
                break;

            case DRDA_CP_RDBCMM:
                //frdbg("__db2_parse_rdbcmm\n");
                i_ret = __db2_parse_rdbcmm(p_st_conn, p_st_hash_report
                                          , p_st_private, i_whole_flg);
                break;

            case DRDA_CP_EXCSQLIMM:
                //frdbg("__db2_parse_excsqlimm\n");
                i_ret = __db2_parse_excsqlimm(p_st_conn, p_st_hash_report
                                             , p_st_private, i_whole_flg);
                break;

            case DRDA_CP_RDBRLLBCK:
                //frdbg("__db2_parse_rdbrllbck\n");
                i_ret = __db2_parse_rdbrllbck(p_st_conn, p_st_hash_report
                                             , p_st_private, i_whole_flg);
                break;

            case DRDA_CP_DSCSQLSTT:
                //frdbg("__db2_parse_dscsqlstt\n");
                i_ret = __db2_parse_dscsqlstt(p_st_conn, p_st_hash_report
                                             , p_st_private, i_whole_flg);
                break;

            case DRDA_CP_EXCSQLSTT:
                //frdbg("__db2_parse_excsqlstt\n");
                i_ret = __db2_parse_excsqlstt(p_st_conn, p_st_hash_report
                                             , p_st_private, i_whole_flg);
                break;

            case DRDA_CP_C004:
                //frdbg("__db2_parse_c004\n");
                i_ret = __db2_parse_c004(p_st_conn, p_st_hash_report
                                        , p_st_private, i_whole_flg);
                break;

            case DRDA_CP_SYNCCTL:
                //frdbg("__db2_parse_syncctl\n");
                i_ret = __db2_parse_syncctl(p_st_conn, p_st_hash_report
                                            , p_st_private, i_whole_flg);
                break;

            /* 现未支持的COMMAND */
            case DRDA_CP_BGNBND:
            case DRDA_CP_BNDCPY:
            case DRDA_CP_BNDDPLY:
            case DRDA_CP_BNDSQLSTT:
            case DRDA_CP_DRPPKG:
            case DRDA_CP_ENDBND:
            case DRDA_CP_GETNXTCHK:
            case DRDA_CP_INTRDBRQS:
            case DRDA_CP_REBIND:
            case DRDA_CP_SNDPKT:
            case DRDA_CP_SYNCRSY:
                //TODO 暂时没有抓到该类型的数据包, 未支持
                frdbg("Command type[%d] is not support now!\n", i_req_cp);
                return APM_L7_ANALYZE_FAIL;

            default:
                frdbg("Unknow command code point[%d]!\n", i_req_cp);
                return APM_L7_ANALYZE_FAIL;
        }

        /* 判断解析结果 */
        if (i_ret == APM_L7_ANALYZE_FAIL || i_ret == APM_L7_ANALYZE_TODO)
        {
            return i_ret;
        }
    }

    /* request解析完了 */
    if (i_whole_flg == DB2_TRUE)
    {
        /* 保留解析结果返回值,初始化分片包信息,设置接下来需要解析的类型 */
        i_sub_ret = i_ret;
        db2_init_fragment(p_st_private->p_st_fragment);
        p_st_private->p_st_req->i_need_req_resp = DB2_RESPONSE;
        /* 上报request数据 */
        i_ret = __db2_report_req(p_st_conn, p_st_hash_report
                                , p_st_private->p_st_req
                                , p_st_private->p_st_sess);
        if (i_ret != APM_L7_ANALYZE_SUCC)
        {
            return APM_L7_ANALYZE_FAIL;
        }
        else
        {
            return APM_L7_ANALYZE_SET_REQ(i_sub_ret);
        }
    }
    else
    {
        return APM_L7_ANALYZE_TODO;
    }
}
